Kaynağa Gözat

make http size check work

Michael Vogt 11 yıl önce
ebeveyn
işleme
a2d40703e4
100 değiştirilmiş dosya ile 3658 ekleme ve 1995 silme
  1. 0 1
      .travis.yml
  2. 1 1
      COMPILING
  3. 2 2
      Makefile
  4. 0 73
      README.ddtp
  5. 181 0
      README.md
  6. 1 1
      apt-inst/contrib/arfile.h
  7. 6 7
      apt-inst/contrib/extracttar.cc
  8. 2 2
      apt-inst/contrib/extracttar.h
  9. 2 2
      apt-inst/deb/debfile.cc
  10. 2 2
      apt-inst/deb/debfile.h
  11. 0 1
      apt-inst/dirstream.cc
  12. 2 2
      apt-inst/dirstream.h
  13. 1 1
      apt-inst/extract.cc
  14. 1 1
      apt-inst/makefile
  15. 469 201
      apt-pkg/acquire-item.cc
  16. 47 36
      apt-pkg/acquire-item.h
  17. 12 0
      apt-pkg/acquire-method.cc
  18. 1 1
      apt-pkg/acquire-method.h
  19. 26 28
      apt-pkg/acquire.cc
  20. 5 2
      apt-pkg/acquire.h
  21. 6 10
      apt-pkg/algorithms.cc
  22. 14 14
      apt-pkg/algorithms.h
  23. 29 29
      apt-pkg/aptconfiguration.cc
  24. 0 3
      apt-pkg/aptconfiguration.h
  25. 3 0
      apt-pkg/cachefile.cc
  26. 119 25
      apt-pkg/cachefilter.cc
  27. 90 27
      apt-pkg/cachefilter.h
  28. 13 3
      apt-pkg/cacheiterators.h
  29. 259 110
      apt-pkg/cacheset.cc
  30. 475 105
      apt-pkg/cacheset.h
  31. 7 3
      apt-pkg/cdrom.cc
  32. 4 1
      apt-pkg/clean.cc
  33. 11 8
      apt-pkg/contrib/cmndline.cc
  34. 0 5
      apt-pkg/contrib/configuration.cc
  35. 6 8
      apt-pkg/contrib/configuration.h
  36. 101 6
      apt-pkg/contrib/fileutl.cc
  37. 16 0
      apt-pkg/contrib/fileutl.h
  38. 18 45
      apt-pkg/contrib/gpgv.cc
  39. 2 2
      apt-pkg/contrib/hashes.cc
  40. 1 1
      apt-pkg/contrib/macros.h
  41. 86 0
      apt-pkg/contrib/proxy.cc
  42. 16 0
      apt-pkg/contrib/proxy.h
  43. 63 17
      apt-pkg/contrib/strutl.cc
  44. 4 2
      apt-pkg/contrib/strutl.h
  45. 61 35
      apt-pkg/deb/debindexfile.cc
  46. 13 12
      apt-pkg/deb/debindexfile.h
  47. 73 31
      apt-pkg/deb/deblistparser.cc
  48. 3 4
      apt-pkg/deb/deblistparser.h
  49. 1 1
      apt-pkg/deb/debmetaindex.h
  50. 2 1
      apt-pkg/deb/debsrcrecords.cc
  51. 1 1
      apt-pkg/deb/debsystem.h
  52. 158 111
      apt-pkg/deb/dpkgpm.cc
  53. 2 14
      apt-pkg/deb/dpkgpm.h
  54. 19 4
      apt-pkg/depcache.cc
  55. 7 18
      apt-pkg/depcache.h
  56. 62 10
      apt-pkg/edsp.cc
  57. 3 3
      apt-pkg/edsp.h
  58. 1 1
      apt-pkg/edsp/edspindexfile.cc
  59. 2 2
      apt-pkg/indexcopy.h
  60. 29 10
      apt-pkg/indexrecords.cc
  61. 5 1
      apt-pkg/indexrecords.h
  62. 2 0
      apt-pkg/install-progress.cc
  63. 3 4
      apt-pkg/install-progress.h
  64. 1 1
      apt-pkg/metaindex.h
  65. 49 2
      apt-pkg/packagemanager.cc
  66. 3 2
      apt-pkg/packagemanager.h
  67. 34 41
      apt-pkg/pkgcache.cc
  68. 112 122
      apt-pkg/pkgcache.h
  69. 115 140
      apt-pkg/pkgcachegen.cc
  70. 30 24
      apt-pkg/pkgcachegen.h
  71. 4 4
      apt-pkg/sourcelist.cc
  72. 0 4
      apt-pkg/sourcelist.h
  73. 24 13
      apt-pkg/srcrecords.cc
  74. 7 2
      apt-pkg/srcrecords.h
  75. 12 1
      apt-pkg/tagfile.cc
  76. 4 3
      apt-pkg/tagfile.h
  77. 2 1
      apt-pkg/update.h
  78. 79 32
      apt-pkg/upgrade.cc
  79. 9 5
      apt-pkg/upgrade.h
  80. 2 2
      apt-private/acqprogress.cc
  81. 3 1
      apt-private/private-cachefile.cc
  82. 46 43
      apt-private/private-cacheset.cc
  83. 17 20
      apt-private/private-cacheset.h
  84. 7 2
      apt-private/private-cmndline.cc
  85. 5 0
      apt-private/private-download.cc
  86. 6 0
      apt-private/private-download.h
  87. 159 9
      apt-private/private-install.cc
  88. 9 151
      apt-private/private-install.h
  89. 18 23
      apt-private/private-list.cc
  90. 205 172
      apt-private/private-output.cc
  91. 4 3
      apt-private/private-output.h
  92. 58 24
      apt-private/private-search.cc
  93. 4 4
      apt-private/private-show.cc
  94. 29 1
      apt-private/private-update.cc
  95. 3 13
      apt-private/private-upgrade.cc
  96. 41 17
      apt-private/private-utils.cc
  97. 2 2
      apt-private/private-utils.h
  98. 4 0
      buildlib/config.h.in
  99. 0 60
      buildlib/debiandoc.mak
  100. 0 0
      buildlib/defaults.mak

+ 0 - 1
.travis.yml

@@ -2,5 +2,4 @@ language: cpp
 before_install:
 before_install:
  - sudo apt-get update -q
  - sudo apt-get update -q
  - sudo ./prepare-release travis-ci
  - sudo ./prepare-release travis-ci
- - sudo apt-get install -q --no-install-recommends stunnel4
 script: make && make test && test/integration/run-tests
 script: make && make test && test/integration/run-tests

+ 1 - 1
COMPILING

@@ -53,7 +53,7 @@ Debian GNU Linux 'potato'
 Debian GNU Linux 'woody'
 Debian GNU Linux 'woody'
   * All Archs
   * All Archs
   - Works flawlessly
   - Works flawlessly
-  - You will want to have debiandoc-sgml and docbook2man installed to get
+  - You will want to have docbook-xml and docbook2man installed to get
     best results.
     best results.
   - No IPv6 Support in glibc's < 2.1.
   - No IPv6 Support in glibc's < 2.1.
 
 

+ 2 - 2
Makefile

@@ -10,7 +10,7 @@ endif
 default: startup all
 default: startup all
 
 
 .PHONY: headers library clean veryclean all binary program doc test update-po
 .PHONY: headers library clean veryclean all binary program doc test update-po
-all headers library clean veryclean binary program doc manpages debiandoc test update-po startup dirs:
+all headers library clean veryclean binary program doc manpages docbook test update-po startup dirs:
 	$(MAKE) -C vendor $@
 	$(MAKE) -C vendor $@
 	$(MAKE) -C apt-pkg $@
 	$(MAKE) -C apt-pkg $@
 	$(MAKE) -C apt-inst $@
 	$(MAKE) -C apt-inst $@
@@ -23,7 +23,7 @@ all headers library clean veryclean binary program doc manpages debiandoc test u
 	$(MAKE) -C po $@
 	$(MAKE) -C po $@
 	$(MAKE) -C test $@
 	$(MAKE) -C test $@
 
 
-all headers library clean veryclean binary program doc manpages debiandoc test update-po: startup dirs
+all headers library clean veryclean binary program doc manpages docbook test update-po: startup dirs
 
 
 dirs: startup
 dirs: startup
 
 

+ 0 - 73
README.ddtp

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

+ 181 - 0
README.md

@@ -0,0 +1,181 @@
+APT
+===
+
+apt is the main commandline package manager for Debian and its derivatives.
+It provides commandline tools for searching and managing as well as querying
+information about packages as well as low-level access to all features
+provided by the libapt-pkg and libapt-inst libraries which higher-level
+package managers can depend upon.
+
+Included tools are:
+
+* apt-get for retrieval of packages and information about them
+  from authenticated sources and for installation, upgrade and
+  removal of packages together with their dependencies
+* apt-cache for querying available information about installed
+  as well as installable packages
+* apt-cdrom to use removable media as a source for packages
+* apt-config as an interface to the configuration settings
+* apt-key as an interface to manage authentication keys
+* apt-extracttemplates to be used by debconf to prompt for configuration
+  questions before installation.
+* apt-ftparchive creates Packages and other index files
+  needed to publish an archive of debian packages
+* apt-sortpkgs is a Packages/Sources file normalizer.
+
+The libraries libapt-pkg and libapt-inst are also maintained as part of this project,
+alongside various additional binaries like the acquire-methods used by them.
+Bindings for Python ([python-apt](https://tracker.debian.org/pkg/python-apt)) and
+Perl ([libapt-pkg-perl](https://tracker.debian.org/pkg/libapt-pkg-perl)) are available as separated projects.
+
+Discussion happens mostly on [the mailinglist](mailto:deity@lists.debian.org) ([archive](https://lists.debian.org/deity/)) and on [IRC](irc://irc.oftc.net/debian-apt).
+Our bugtracker as well as a general overview can be found at the [Debian Tracker page](https://tracker.debian.org/pkg/apt).
+
+
+Contributing
+------------
+APT is maintained in git, the official repository being located at
+`git://anonscm.debian.org/apt/apt.git` ([webgit](http://anonscm.debian.org/gitweb/?p=apt/apt.git)),
+but also available at other locations like [GitHub](https://github.com/Debian/apt).
+
+The default branch is `debian/sid`, other branches targeted at different
+derivatives and releases being used as needed. Various topic branches in
+different stages of completion might be branched of from those, which you
+are encouraged to do as well.
+
+### Coding
+
+APT uses its own autoconf based build system, see [README.make](http://anonscm.debian.org/gitweb/?p=apt/apt.git;a=blob;f=README.make)
+for the glory details, but to get started, just run:
+
+	$ make
+
+from a fresh git checkout.
+
+The source code uses in most parts a relatively uncommon indent convention,
+namely 3 spaces with 8 space tab (see [doc/style.txt](http://anonscm.debian.org/gitweb/?p=apt/apt.git;a=blob;f=doc/style.txt) for more on this).
+Adhering to it avoids unnecessary code-churn destroying history (aka: `git blame`)
+and you are therefore encouraged to write patches in this style.
+Your editor can surely help you with this, for vim the settings would be
+`setlocal shiftwidth=3 noexpandtab tabstop=8`
+(the later two are the default configuration and could therefore be omitted).
+
+### Translations
+
+While we welcome contributions here, we highly encourage you to contact the [Debian Internationalization (i18n) team](https://wiki.debian.org/Teams/I18n).
+Various language teams have formed which can help you creating, maintaining
+and improving a translation, while we could only do a basic syntax check of the
+file format…
+
+Further more, Translating APT is split into two independent parts:
+The program translation, meaning the messages printed by the tools,
+as well as the manpages and other documentation shipped with APT.
+
+### Bug triage
+
+Software tools like APT which are used by thousands of users every
+day have a steady flow of incoming bugreports. Not all of them are really
+bugs in APT: It can be packaging bugs like failing maintainer scripts a
+user reports against apt, because apt was the command he executed leading
+to this failure or various wishlist items for new features. Given enough time
+also the occasional duplicate enters the system.
+Our bugtracker is therefore full with open bugreports which are waiting for you! ;)
+
+Testing
+-------
+
+### Manual execution
+
+When you make changes and want to run them manually, make sure your
+`$LD_LIBRARY_PATH` points to the libraries you have built, e.g. via:
+
+	$ export LD_LIBRARY_PATH=$(pwd)/build/bin
+	$ ./build/bin/apt-get moo
+
+
+### Integration tests
+
+There is a extensive integration testsuite available which can be run via:
+
+	$ ./test/integration/run-tests
+
+While these tests are not executed at package build-time as they require additional
+dependencies, the repository contains the configuration needed to run them on [Travis CI](https://travis-ci.org/)
+as well as via autopkgtests e.g. on [Debian Continuous Integration](http://ci.debian.net/?q=apt#package/apt).
+
+A testcase here is a shellscript embedded in a framework creating an environment in which
+apt tools can be used naturally without root-rights to test every aspect of its behavior
+itself as well as in conjunction with dpkg and other tools while working with packages.
+
+
+### Unit tests
+
+These tests are gtest-dev based, reside in `./test/libapt` and can be run with `make test`.
+They are executed at package build-time, but not by `make`.
+
+Debugging
+---------
+
+APT does many things, so there is no central debug mode which could be
+activated. It uses instead various config-options to activate debug output
+in certain areas. The following describes some common scenarios and generally
+useful options, but is in no way exhaustive.
+
+Note that you should *NEVER* use these settings as root to avoid accidents.
+Similation mode (`-s`) is usually sufficient to help you run apt as a non-root user.
+
+### Using different state files
+
+If a dependency solver bug is reported, but can't be reproduced by the
+triager easily, it is beneficial to ask the reporter for the
+`/var/lib/dpkg/status` file, which includes the packages installed on the
+system and in which version. Such a file can then be used via the option
+`dir::state::status`. Beware of different architecture settings!
+Bugreports usually include this information in the template. Assuming you
+already have the `Packages` files for the architecture (see `sources.list`
+manpage for the `arch=` option) you can change to a different architecture
+with a config file like:
+
+	APT::Architecture "arch1";
+	#clear APT::Architectures;
+	APT:: Architectures { "arch1"; "arch2"; }
+
+If a certain mirror state is needed, see if you can reproduce it with [snapshot.debian.org](http://snapshot.debian.org/).
+Your sources.list file (`dir::etc::sourcelist`) has to be correctly mention the repository,
+but if it does, you can use different downloaded archive state files via `dir::state::lists`.
+
+In case manually vs. automatically installed matters, you can ask the reporter for
+the `/var/lib/apt/extended_states` file and use it with `dir::state::extended_states`.
+
+### Dependency resolution
+
+APT works in its internal resolver in two stages: First all packages are visited
+and marked for installation, keep back or removal. Option `Debug::pkgDepCache::Marker`
+shows this. This also decides which packages are to be installed to satisfy dependencies,
+which can be seen by `Debug::pkgDepCache::AutoInstall`. After this is done, we might
+be in a situation in which two packages want to be installed, but only on of them can be.
+It is the job of the pkgProblemResolver to decide which of two packages 'wins' and can
+therefore decide what has to happen. You can see the contenders as well as their fight and
+the resulting resolution with `Debug::pkgProblemResolver`.
+
+### Downloading files
+
+Various binaries (called 'methods') are tasked with downloading files. The Acquire system
+talks to them via simple text protocol. Depending on which side you want to see, either
+`Debug::pkgAcquire::Worker` or `Debug::Acquire::http` (or similar) will show the messages.
+
+The integration tests use a simple self-built webserver which also logs. If you find that
+the http(s) methods do not behave like they should be try to implement this behavior in the
+webserver for simpler and more controlled testing.
+
+### Installation order
+
+Dependencies are solved, packages downloaded: Everything read for the installation!
+The last step in the chain is often forgotten, but still very important:
+Packages have to be installed in a particular order so that their dependencies are
+satisfied, but at the same time you don't want to install very important and optional
+packages at the same time if possible, so that a broken optional package does not
+block the correct installation of very important packages. Which option to use depends on
+if you are interested in the topology sorting (`Debug::pkgOrderList`), the dependency-aware
+cycle and unconfigured prevention (`Debug::pkgPackageManager`) or the actual calls
+to dpkg (`Debug::pkgDpkgPm`).

+ 1 - 1
apt-inst/contrib/arfile.h

@@ -61,7 +61,7 @@ struct ARArchive::Member
    unsigned long long Size;
    unsigned long long Size;
    
    
    // Location of the data.
    // Location of the data.
-   unsigned long Start;
+   unsigned long long Start;
    Member *Next;
    Member *Next;
    
    
    Member() : Start(0), Next(0) {};
    Member() : Start(0), Next(0) {};

+ 6 - 7
apt-inst/contrib/extracttar.cc

@@ -60,9 +60,8 @@ struct ExtractTar::TarHeader
 // ExtractTar::ExtractTar - Constructor					/*{{{*/
 // ExtractTar::ExtractTar - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-ExtractTar::ExtractTar(FileFd &Fd,unsigned long Max,string DecompressionProgram) : File(Fd), 
-                         MaxInSize(Max), DecompressProg(DecompressionProgram)
-
+ExtractTar::ExtractTar(FileFd &Fd,unsigned long long Max,string DecompressionProgram)
+	: File(Fd), MaxInSize(Max), DecompressProg(DecompressionProgram)
 {
 {
    GZPid = -1;
    GZPid = -1;
    Eof = false;
    Eof = false;
@@ -267,7 +266,7 @@ bool ExtractTar::Go(pkgDirStream &Stream)
 
 
 	 case GNU_LongLink:
 	 case GNU_LongLink:
 	 {
 	 {
-	    unsigned long Length = Itm.Size;
+	    unsigned long long Length = Itm.Size;
 	    unsigned char Block[512];
 	    unsigned char Block[512];
 	    while (Length > 0)
 	    while (Length > 0)
 	    {
 	    {
@@ -286,7 +285,7 @@ bool ExtractTar::Go(pkgDirStream &Stream)
 	 
 	 
 	 case GNU_LongName:
 	 case GNU_LongName:
 	 {
 	 {
-	    unsigned long Length = Itm.Size;
+	    unsigned long long Length = Itm.Size;
 	    unsigned char Block[512];
 	    unsigned char Block[512];
 	    while (Length > 0)
 	    while (Length > 0)
 	    {
 	    {
@@ -315,11 +314,11 @@ bool ExtractTar::Go(pkgDirStream &Stream)
 	    return false;
 	    return false;
       
       
       // Copy the file over the FD
       // Copy the file over the FD
-      unsigned long Size = Itm.Size;
+      unsigned long long Size = Itm.Size;
       while (Size != 0)
       while (Size != 0)
       {
       {
 	 unsigned char Junk[32*1024];
 	 unsigned char Junk[32*1024];
-	 unsigned long Read = min(Size,(unsigned long)sizeof(Junk));
+	 unsigned long Read = min(Size, (unsigned long long)sizeof(Junk));
 	 if (InFd.Read(Junk,((Read+511)/512)*512) == false)
 	 if (InFd.Read(Junk,((Read+511)/512)*512) == false)
 	    return false;
 	    return false;
 	 
 	 

+ 2 - 2
apt-inst/contrib/extracttar.h

@@ -39,7 +39,7 @@ class ExtractTar
                   GNU_LongLink = 'K',GNU_LongName = 'L'};
                   GNU_LongLink = 'K',GNU_LongName = 'L'};
 
 
    FileFd &File;
    FileFd &File;
-   unsigned long MaxInSize;
+   unsigned long long MaxInSize;
    int GZPid;
    int GZPid;
    FileFd InFd;
    FileFd InFd;
    bool Eof;
    bool Eof;
@@ -53,7 +53,7 @@ class ExtractTar
 
 
    bool Go(pkgDirStream &Stream);
    bool Go(pkgDirStream &Stream);
    
    
-   ExtractTar(FileFd &Fd,unsigned long Max,std::string DecompressionProgram);
+   ExtractTar(FileFd &Fd,unsigned long long Max,std::string DecompressionProgram);
    virtual ~ExtractTar();
    virtual ~ExtractTar();
 };
 };
 
 

+ 2 - 2
apt-inst/deb/debfile.cc

@@ -203,7 +203,7 @@ bool debDebFile::MemControlExtract::DoItem(Item &Itm,int &Fd)
 /* Just memcopy the block from the tar extractor and put it in the right
 /* Just memcopy the block from the tar extractor and put it in the right
    place in the pre-allocated memory block. */
    place in the pre-allocated memory block. */
 bool debDebFile::MemControlExtract::Process(Item &/*Itm*/,const unsigned char *Data,
 bool debDebFile::MemControlExtract::Process(Item &/*Itm*/,const unsigned char *Data,
-			     unsigned long Size,unsigned long Pos)
+			     unsigned long long Size,unsigned long long Pos)
 {
 {
    memcpy(Control + Pos, Data,Size);
    memcpy(Control + Pos, Data,Size);
    return true;
    return true;
@@ -232,7 +232,7 @@ bool debDebFile::MemControlExtract::Read(debDebFile &Deb)
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* The given memory block is loaded into the parser and parsed as a control
 /* The given memory block is loaded into the parser and parsed as a control
    record. */
    record. */
-bool debDebFile::MemControlExtract::TakeControl(const void *Data,unsigned long Size)
+bool debDebFile::MemControlExtract::TakeControl(const void *Data,unsigned long long Size)
 {
 {
    delete [] Control;
    delete [] Control;
    Control = new char[Size+2];
    Control = new char[Size+2];

+ 2 - 2
apt-inst/deb/debfile.h

@@ -81,12 +81,12 @@ class debDebFile::MemControlExtract : public pkgDirStream
    // Members from DirStream
    // Members from DirStream
    virtual bool DoItem(Item &Itm,int &Fd);
    virtual bool DoItem(Item &Itm,int &Fd);
    virtual bool Process(Item &Itm,const unsigned char *Data,
    virtual bool Process(Item &Itm,const unsigned char *Data,
-			unsigned long Size,unsigned long Pos);
+			unsigned long long Size,unsigned long long Pos);
    
    
 
 
    // Helpers
    // Helpers
    bool Read(debDebFile &Deb);
    bool Read(debDebFile &Deb);
-   bool TakeControl(const void *Data,unsigned long Size);
+   bool TakeControl(const void *Data,unsigned long long Size);
       
       
    MemControlExtract() : IsControl(false), Control(0), Length(0), Member("control") {};
    MemControlExtract() : IsControl(false), Control(0), Length(0), Member("control") {};
    MemControlExtract(std::string Member) : IsControl(false), Control(0), Length(0), Member(Member) {};
    MemControlExtract(std::string Member) : IsControl(false), Control(0), Length(0), Member(Member) {};

+ 0 - 1
apt-inst/dirstream.cc

@@ -76,7 +76,6 @@ bool pkgDirStream::DoItem(Item &Itm,int &Fd)
 	 if(mkdir(Itm.Name,Itm.Mode) < 0)
 	 if(mkdir(Itm.Name,Itm.Mode) < 0)
 	    return false;
 	    return false;
 	 return true;
 	 return true;
-	 break;
       }
       }
       case Item::FIFO:
       case Item::FIFO:
       break;
       break;

+ 2 - 2
apt-inst/dirstream.h

@@ -37,10 +37,10 @@ class pkgDirStream
 	           Directory, FIFO} Type;
 	           Directory, FIFO} Type;
       char *Name;
       char *Name;
       char *LinkTarget;
       char *LinkTarget;
+      unsigned long long Size;
       unsigned long Mode;
       unsigned long Mode;
       unsigned long UID;
       unsigned long UID;
       unsigned long GID;
       unsigned long GID;
-      unsigned long Size;
       unsigned long MTime;
       unsigned long MTime;
       unsigned long Major;
       unsigned long Major;
       unsigned long Minor;
       unsigned long Minor;
@@ -50,7 +50,7 @@ class pkgDirStream
    virtual bool Fail(Item &Itm,int Fd);
    virtual bool Fail(Item &Itm,int Fd);
    virtual bool FinishedFile(Item &Itm,int Fd);
    virtual bool FinishedFile(Item &Itm,int Fd);
    virtual bool Process(Item &/*Itm*/,const unsigned char * /*Data*/,
    virtual bool Process(Item &/*Itm*/,const unsigned char * /*Data*/,
-			unsigned long /*Size*/,unsigned long /*Pos*/) {return true;};
+			unsigned long long /*Size*/,unsigned long long /*Pos*/) {return true;};
       
       
    virtual ~pkgDirStream() {};   
    virtual ~pkgDirStream() {};   
 };
 };

+ 1 - 1
apt-inst/extract.cc

@@ -404,7 +404,7 @@ bool pkgExtract::HandleOverwrites(pkgFLCache::NodeIterator Nde,
       // Now see if this package matches one in a replace depends
       // Now see if this package matches one in a replace depends
       pkgCache::DepIterator Dep = Ver.DependsList();
       pkgCache::DepIterator Dep = Ver.DependsList();
       bool Ok = false;
       bool Ok = false;
-      for (; Dep.end() == false; Dep++)
+      for (; Dep.end() == false; ++Dep)
       {
       {
 	 if (Dep->Type != pkgCache::Dep::Replaces)
 	 if (Dep->Type != pkgCache::Dep::Replaces)
 	    continue;
 	    continue;

+ 1 - 1
apt-inst/makefile

@@ -14,7 +14,7 @@ include ../buildlib/libversion.mak
 
 
 # The library name
 # The library name
 LIBRARY=apt-inst
 LIBRARY=apt-inst
-MAJOR=1.5
+MAJOR=1.6
 MINOR=0
 MINOR=0
 SLIBS=$(PTHREADLIB) -lapt-pkg
 SLIBS=$(PTHREADLIB) -lapt-pkg
 APT_DOMAIN:=libapt-inst$(MAJOR)
 APT_DOMAIN:=libapt-inst$(MAJOR)

+ 469 - 201
apt-pkg/acquire-item.cc

@@ -64,6 +64,10 @@ static void printHashSumComparision(std::string const &URI, HashStringList const
 									/*}}}*/
 									/*}}}*/
 
 
 // Acquire::Item::Item - Constructor					/*{{{*/
 // Acquire::Item::Item - Constructor					/*{{{*/
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
 pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes) :
 pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes) :
    Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false),
    Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false),
    Local(false), QueueCounter(0), ExpectedAdditionalItems(0),
    Local(false), QueueCounter(0), ExpectedAdditionalItems(0),
@@ -72,6 +76,9 @@ pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes)
    Owner->Add(this);
    Owner->Add(this);
    Status = StatIdle;
    Status = StatIdle;
 }
 }
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 									/*}}}*/
 									/*}}}*/
 // Acquire::Item::~Item - Destructor					/*{{{*/
 // Acquire::Item::~Item - Destructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
@@ -369,7 +376,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
    Desc.URI = Target->URI + ".diff/Index";
    Desc.URI = Target->URI + ".diff/Index";
 
 
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
-   DestFile += URItoFileName(Target->URI) + string(".DiffIndex");
+   DestFile += URItoFileName(Desc.URI);
 
 
    if(Debug)
    if(Debug)
       std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
       std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
@@ -385,9 +392,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
       Desc.URI.substr(0,strlen("file:/")) == "file:/")
       Desc.URI.substr(0,strlen("file:/")) == "file:/")
    {
    {
       // we don't have a pkg file or we don't want to queue
       // we don't have a pkg file or we don't want to queue
-      if(Debug)
-	 std::clog << "No index file, local or canceld by user" << std::endl;
-      Failed("", NULL);
+      Failed("No index file, local or canceld by user", NULL);
       return;
       return;
    }
    }
 
 
@@ -405,7 +410,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
 string pkgAcqDiffIndex::Custom600Headers() const
 string pkgAcqDiffIndex::Custom600Headers() const
 {
 {
    string Final = _config->FindDir("Dir::State::lists");
    string Final = _config->FindDir("Dir::State::lists");
-   Final += URItoFileName(RealURI) + string(".IndexDiff");
+   Final += URItoFileName(Desc.URI);
    
    
    if(Debug)
    if(Debug)
       std::clog << "Custom600Header-IMS: " << Final << std::endl;
       std::clog << "Custom600Header-IMS: " << Final << std::endl;
@@ -419,156 +424,264 @@ string pkgAcqDiffIndex::Custom600Headers() const
 									/*}}}*/
 									/*}}}*/
 bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
 bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
 {
 {
+   // failing here is fine: our caller will take care of trying to
+   // get the complete file if patching fails
    if(Debug)
    if(Debug)
       std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile
       std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile
 	 << std::endl;
 	 << std::endl;
 
 
-   pkgTagSection Tags;
-   string ServerSha1;
-   vector<DiffInfo> available_patches;
-   
    FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
    FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
    pkgTagFile TF(&Fd);
    pkgTagFile TF(&Fd);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;
 
 
-   if(TF.Step(Tags) == true)
+   pkgTagSection Tags;
+   if(unlikely(TF.Step(Tags) == false))
+      return false;
+
+   HashStringList ServerHashes;
+   unsigned long long ServerSize = 0;
+
+   for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
    {
    {
-      bool found = false;
-      DiffInfo d;
-      string size;
+      std::string tagname = *type;
+      tagname.append("-Current");
+      std::string const tmp = Tags.FindS(tagname.c_str());
+      if (tmp.empty() == true)
+	 continue;
 
 
-      string const tmp = Tags.FindS("SHA1-Current");
+      string hash;
+      unsigned long long size;
       std::stringstream ss(tmp);
       std::stringstream ss(tmp);
-      ss >> ServerSha1 >> size;
-      unsigned long const ServerSize = atol(size.c_str());
+      ss >> hash >> size;
+      if (unlikely(hash.empty() == true))
+	 continue;
+      if (unlikely(ServerSize != 0 && ServerSize != size))
+	 continue;
+      ServerHashes.push_back(HashString(*type, hash));
+      ServerSize = size;
+   }
 
 
-      FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
-      SHA1Summation SHA1;
-      SHA1.AddFD(fd);
-      string const local_sha1 = SHA1.Result();
+   if (ServerHashes.usable() == false)
+   {
+      if (Debug == true)
+	 std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Did not find a good hashsum in the index" << std::endl;
+      return false;
+   }
 
 
-      if(local_sha1 == ServerSha1)
-      {
-	 // we have the same sha1 as the server so we are done here
-	 if(Debug)
-	    std::clog << "Package file is up-to-date" << std::endl;
-	 // list cleanup needs to know that this file as well as the already
-	 // present index is ours, so we create an empty diff to save it for us
-	 new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser, 
-                              ServerSha1, available_patches);
-	 return true;
-      }
-      else
+   if (ServerHashes != HashSums())
+   {
+      if (Debug == true)
+	 std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Index has different hashes than parser, probably older, so fail pdiffing" << std::endl;
+      return false;
+   }
+
+   if (ServerHashes.VerifyFile(CurrentPackagesFile) == true)
+   {
+      // we have the same sha1 as the server so we are done here
+      if(Debug)
+	 std::clog << "pkgAcqDiffIndex: Package file is up-to-date" << std::endl;
+      // list cleanup needs to know that this file as well as the already
+      // present index is ours, so we create an empty diff to save it for us
+      new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser);
+      return true;
+   }
+
+   FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
+   Hashes LocalHashesCalc;
+   LocalHashesCalc.AddFD(fd);
+   HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList();
+
+   if(Debug)
+      std::clog << "Server-Current: " << ServerHashes.find(NULL)->toStr() << " and we start at "
+	 << fd.Name() << " " << fd.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl;
+
+   // parse all of (provided) history
+   vector<DiffInfo> available_patches;
+   bool firstAcceptedHashes = true;
+   for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+   {
+      if (LocalHashes.find(*type) == NULL)
+	 continue;
+
+      std::string tagname = *type;
+      tagname.append("-History");
+      std::string const tmp = Tags.FindS(tagname.c_str());
+      if (tmp.empty() == true)
+	 continue;
+
+      string hash, filename;
+      unsigned long long size;
+      std::stringstream ss(tmp);
+
+      while (ss >> hash >> size >> filename)
       {
       {
-	 if(Debug)
-	    std::clog << "SHA1-Current: " << ServerSha1 << " and we start at "<< fd.Name() << " " << fd.Size() << " " << local_sha1 << std::endl;
+	 if (unlikely(hash.empty() == true || filename.empty() == true))
+	    continue;
 
 
-	 // check the historie and see what patches we need
-	 string const history = Tags.FindS("SHA1-History");
-	 std::stringstream hist(history);
-	 while(hist >> d.sha1 >> size >> d.file)
+	 // see if we have a record for this file already
+	 std::vector<DiffInfo>::iterator cur = available_patches.begin();
+	 for (; cur != available_patches.end(); ++cur)
 	 {
 	 {
-	    // read until the first match is found
-	    // from that point on, we probably need all diffs
-	    if(d.sha1 == local_sha1) 
-	       found=true;
-	    else if (found == false)
+	    if (cur->file != filename || unlikely(cur->result_size != size))
 	       continue;
 	       continue;
-
-	    if(Debug)
-	       std::clog << "Need to get diff: " << d.file << std::endl;
-	    available_patches.push_back(d);
+	    cur->result_hashes.push_back(HashString(*type, hash));
+	    break;
 	 }
 	 }
-
-	 if (available_patches.empty() == false)
+	 if (cur != available_patches.end())
+	    continue;
+	 if (firstAcceptedHashes == true)
 	 {
 	 {
-	    // patching with too many files is rather slow compared to a fast download
-	    unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0);
-	    if (fileLimit != 0 && fileLimit < available_patches.size())
-	    {
-	       if (Debug)
-		  std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit
-			<< ") so fallback to complete download" << std::endl;
-	       return false;
-	    }
-
-	    // see if the patches are too big
-	    found = false; // it was true and it will be true again at the end
-	    d = *available_patches.begin();
-	    string const firstPatch = d.file;
-	    unsigned long patchesSize = 0;
-	    std::stringstream patches(Tags.FindS("SHA1-Patches"));
-	    while(patches >> d.sha1 >> size >> d.file)
-	    {
-	       if (firstPatch == d.file)
-		  found = true;
-	       else if (found == false)
-		  continue;
-
-	       patchesSize += atol(size.c_str());
-	    }
-	    unsigned long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100);
-	    if (sizeLimit > 0 && (sizeLimit/100) < patchesSize)
-	    {
-	       if (Debug)
-		  std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100
-			<< ") so fallback to complete download" << std::endl;
-	       return false;
-	    }
+	    DiffInfo next;
+	    next.file = filename;
+	    next.result_hashes.push_back(HashString(*type, hash));
+	    next.result_size = size;
+	    next.patch_size = 0;
+	    available_patches.push_back(next);
+	 }
+	 else
+	 {
+	    if (Debug == true)
+	       std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename
+		  << " wasn't in the list for the first parsed hash! (history)" << std::endl;
+	    break;
 	 }
 	 }
       }
       }
+      firstAcceptedHashes = false;
+   }
+
+   if (unlikely(available_patches.empty() == true))
+   {
+      if (Debug)
+	 std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": "
+	    << "Couldn't find any patches for the patch series." << std::endl;
+      return false;
+   }
+
+   for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+   {
+      if (LocalHashes.find(*type) == NULL)
+	 continue;
+
+      std::string tagname = *type;
+      tagname.append("-Patches");
+      std::string const tmp = Tags.FindS(tagname.c_str());
+      if (tmp.empty() == true)
+	 continue;
 
 
-      // we have something, queue the next diff
-      if(found)
+      string hash, filename;
+      unsigned long long size;
+      std::stringstream ss(tmp);
+
+      while (ss >> hash >> size >> filename)
       {
       {
-	 // queue the diffs
-	 string::size_type const last_space = Description.rfind(" ");
-	 if(last_space != string::npos)
-	    Description.erase(last_space, Description.size()-last_space);
-
-	 /* decide if we should download patches one by one or in one go:
-	    The first is good if the server merges patches, but many don't so client
-	    based merging can be attempt in which case the second is better.
-	    "bad things" will happen if patches are merged on the server,
-	    but client side merging is attempt as well */
-	 bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true);
-	 if (pdiff_merge == true)
-	 {
-	    // reprepro adds this flag if it has merged patches on the server
-	    std::string const precedence = Tags.FindS("X-Patch-Precedence");
-	    pdiff_merge = (precedence != "merged");
-	 }
+	 if (unlikely(hash.empty() == true || filename.empty() == true))
+	    continue;
 
 
-	 if (pdiff_merge == false)
-         {
-	    new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
-                                 ServerSha1, available_patches);
-         }
-         else
+	 // see if we have a record for this file already
+	 std::vector<DiffInfo>::iterator cur = available_patches.begin();
+	 for (; cur != available_patches.end(); ++cur)
 	 {
 	 {
-	    std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
-	    for(size_t i = 0; i < available_patches.size(); ++i)
-	       (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, Target,
-                                                       ExpectedHashes,
-                                                       MetaIndexParser,
-                                                       available_patches[i],
-                                                       diffs);
+	    if (cur->file != filename)
+	       continue;
+	    if (unlikely(cur->patch_size != 0 && cur->patch_size != size))
+	       continue;
+	    cur->patch_hashes.push_back(HashString(*type, hash));
+	    cur->patch_size = size;
+	    break;
 	 }
 	 }
-
-	 Complete = false;
-	 Status = StatDone;
-	 Dequeue();
-	 return true;
+	 if (cur != available_patches.end())
+	       continue;
+	 if (Debug == true)
+	    std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename
+	       << " wasn't in the list for the first parsed hash! (patches)" << std::endl;
+	 break;
       }
       }
    }
    }
-   
-   // Nothing found, report and return false
-   // Failing here is ok, if we return false later, the full
-   // IndexFile is queued
-   if(Debug)
-      std::clog << "Can't find a patch in the index file" << std::endl;
-   return false;
+
+   bool foundStart = false;
+   for (std::vector<DiffInfo>::iterator cur = available_patches.begin();
+	 cur != available_patches.end(); ++cur)
+   {
+      if (LocalHashes != cur->result_hashes)
+	 continue;
+
+      available_patches.erase(available_patches.begin(), cur);
+      foundStart = true;
+      break;
+   }
+
+   if (foundStart == false || unlikely(available_patches.empty() == true))
+   {
+      if (Debug)
+	 std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": "
+	    << "Couldn't find the start of the patch series." << std::endl;
+      return false;
+   }
+
+   // patching with too many files is rather slow compared to a fast download
+   unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0);
+   if (fileLimit != 0 && fileLimit < available_patches.size())
+   {
+      if (Debug)
+	 std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit
+	    << ") so fallback to complete download" << std::endl;
+      return false;
+   }
+
+   // calculate the size of all patches we have to get
+   // note that all sizes are uncompressed, while we download compressed files
+   unsigned long long patchesSize = 0;
+   for (std::vector<DiffInfo>::const_iterator cur = available_patches.begin();
+	 cur != available_patches.end(); ++cur)
+      patchesSize += cur->patch_size;
+   unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100);
+   if (false && sizeLimit > 0 && (sizeLimit/100) < patchesSize)
+   {
+      if (Debug)
+	 std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100
+	    << ") so fallback to complete download" << std::endl;
+      return false;
+   }
+
+   // we have something, queue the diffs
+   string::size_type const last_space = Description.rfind(" ");
+   if(last_space != string::npos)
+      Description.erase(last_space, Description.size()-last_space);
+
+   /* decide if we should download patches one by one or in one go:
+      The first is good if the server merges patches, but many don't so client
+      based merging can be attempt in which case the second is better.
+      "bad things" will happen if patches are merged on the server,
+      but client side merging is attempt as well */
+   bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true);
+   if (pdiff_merge == true)
+   {
+      // reprepro adds this flag if it has merged patches on the server
+      std::string const precedence = Tags.FindS("X-Patch-Precedence");
+      pdiff_merge = (precedence != "merged");
+   }
+
+   if (pdiff_merge == false)
+   {
+      new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
+	    available_patches);
+   }
+   else
+   {
+      std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
+      for(size_t i = 0; i < available_patches.size(); ++i)
+	 (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, Target,
+	       ExpectedHashes,
+	       MetaIndexParser,
+	       available_patches[i],
+	       diffs);
+   }
+
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+   return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
 void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/*{{{*/
 void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/*{{{*/
@@ -606,7 +719,7 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList
    DestFile = FinalFile;
    DestFile = FinalFile;
 
 
    if(!ParseDiffIndex(DestFile))
    if(!ParseDiffIndex(DestFile))
-      return Failed("", NULL);
+      return Failed("Parsing pdiff Index failed", NULL);
 
 
    Complete = true;
    Complete = true;
    Status = StatDone;
    Status = StatDone;
@@ -623,12 +736,10 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
                                    struct IndexTarget const * const Target,
                                    struct IndexTarget const * const Target,
                                    HashStringList const &ExpectedHashes,
                                    HashStringList const &ExpectedHashes,
                                    indexRecords *MetaIndexParser,
                                    indexRecords *MetaIndexParser,
-				   string ServerSha1,
 				   vector<DiffInfo> diffs)
 				   vector<DiffInfo> diffs)
    : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
    : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
-     available_patches(diffs), ServerSha1(ServerSha1)
+     available_patches(diffs)
 {
 {
-   
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile += URItoFileName(Target->URI);
    DestFile += URItoFileName(Target->URI);
 
 
@@ -703,15 +814,21 @@ bool pkgAcqIndexDiffs::QueueNextDiff()					/*{{{*/
    FinalFile += URItoFileName(RealURI);
    FinalFile += URItoFileName(RealURI);
 
 
    FileFd fd(FinalFile, FileFd::ReadOnly);
    FileFd fd(FinalFile, FileFd::ReadOnly);
-   SHA1Summation SHA1;
-   SHA1.AddFD(fd);
-   string local_sha1 = string(SHA1.Result());
+   Hashes LocalHashesCalc;
+   LocalHashesCalc.AddFD(fd);
+   HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList();
+
    if(Debug)
    if(Debug)
-      std::clog << "QueueNextDiff: " 
-		<< FinalFile << " (" << local_sha1 << ")"<<std::endl;
+      std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl;
+
+   if (unlikely(LocalHashes.usable() == false || ExpectedHashes.usable() == false))
+   {
+      Failed("Local/Expected hashes are not usable", NULL);
+      return false;
+   }
 
 
    // final file reached before all patches are applied
    // final file reached before all patches are applied
-   if(local_sha1 == ServerSha1)
+   if(LocalHashes == ExpectedHashes)
    {
    {
       Finish(true);
       Finish(true);
       return true;
       return true;
@@ -719,10 +836,10 @@ bool pkgAcqIndexDiffs::QueueNextDiff()					/*{{{*/
 
 
    // remove all patches until the next matching patch is found
    // remove all patches until the next matching patch is found
    // this requires the Index file to be ordered
    // this requires the Index file to be ordered
-   for(vector<DiffInfo>::iterator I=available_patches.begin();
+   for(vector<DiffInfo>::iterator I = available_patches.begin();
        available_patches.empty() == false &&
        available_patches.empty() == false &&
 	  I != available_patches.end() &&
 	  I != available_patches.end() &&
-	  I->sha1 != local_sha1;
+	  I->result_hashes != LocalHashes;
        ++I)
        ++I)
    {
    {
       available_patches.erase(I);
       available_patches.erase(I);
@@ -731,7 +848,7 @@ bool pkgAcqIndexDiffs::QueueNextDiff()					/*{{{*/
    // error checking and falling back if no patch was found
    // error checking and falling back if no patch was found
    if(available_patches.empty() == true)
    if(available_patches.empty() == true)
    {
    {
-      Failed("", NULL);
+      Failed("No patches left to reach target", NULL);
       return false;
       return false;
    }
    }
 
 
@@ -743,7 +860,7 @@ bool pkgAcqIndexDiffs::QueueNextDiff()					/*{{{*/
 
 
    if(Debug)
    if(Debug)
       std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
       std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
-   
+
    QueueURI(Desc);
    QueueURI(Desc);
 
 
    return true;
    return true;
@@ -763,6 +880,17 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi
    // success in downloading a diff, enter ApplyDiff state
    // success in downloading a diff, enter ApplyDiff state
    if(State == StateFetchDiff)
    if(State == StateFetchDiff)
    {
    {
+      FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip);
+      class Hashes LocalHashesCalc;
+      LocalHashesCalc.AddFD(fd);
+      HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList();
+
+      if (fd.Size() != available_patches[0].patch_size ||
+	    available_patches[0].patch_hashes != LocalHashes)
+      {
+	 Failed("Patch has Size/Hashsum mismatch", NULL);
+	 return;
+      }
 
 
       // rred excepts the patch as $FinalFile.ed
       // rred excepts the patch as $FinalFile.ed
       Rename(DestFile,FinalFile+".ed");
       Rename(DestFile,FinalFile+".ed");
@@ -774,7 +902,15 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi
       Local = true;
       Local = true;
       Desc.URI = "rred:" + FinalFile;
       Desc.URI = "rred:" + FinalFile;
       QueueURI(Desc);
       QueueURI(Desc);
+      ActiveSubprocess = "rred";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
       Mode = "rred";
       Mode = "rred";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
       return;
       return;
    } 
    } 
 
 
@@ -799,7 +935,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi
       if(available_patches.empty() == false) {
       if(available_patches.empty() == false) {
 	 new pkgAcqIndexDiffs(Owner, Target,
 	 new pkgAcqIndexDiffs(Owner, Target,
 			      ExpectedHashes, MetaIndexParser,
 			      ExpectedHashes, MetaIndexParser,
-                              ServerSha1, available_patches);
+			      available_patches);
 	 return Finish();
 	 return Finish();
       } else 
       } else 
 	 return Finish(true);
 	 return Finish(true);
@@ -871,6 +1007,17 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
 
 
    if (State == StateFetchDiff)
    if (State == StateFetchDiff)
    {
    {
+      FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip);
+      class Hashes LocalHashesCalc;
+      LocalHashesCalc.AddFD(fd);
+      HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList();
+
+      if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes)
+      {
+	 Failed("Patch has Size/Hashsum mismatch", NULL);
+	 return;
+      }
+
       // rred expects the patch as $FinalFile.ed.$patchname.gz
       // rred expects the patch as $FinalFile.ed.$patchname.gz
       Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz");
       Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz");
 
 
@@ -894,7 +1041,15 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
       Local = true;
       Local = true;
       Desc.URI = "rred:" + FinalFile;
       Desc.URI = "rred:" + FinalFile;
       QueueURI(Desc);
       QueueURI(Desc);
+      ActiveSubprocess = "rred";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
       Mode = "rred";
       Mode = "rred";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
       return;
       return;
    }
    }
    // success in download/apply all diffs, clean up
    // success in download/apply all diffs, clean up
@@ -952,8 +1107,6 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
    }
    }
    CompressionExtension = comprExt;
    CompressionExtension = comprExt;
 
 
-   Verify = true;
-
    Init(URI, URIDesc, ShortDesc);
    Init(URI, URIDesc, ShortDesc);
 }
 }
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
@@ -979,13 +1132,6 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
    if (CompressionExtension.empty() == false)
    if (CompressionExtension.empty() == false)
       CompressionExtension.erase(CompressionExtension.end()-1);
       CompressionExtension.erase(CompressionExtension.end()-1);
 
 
-   // only verify non-optional targets, see acquire-item.h for a FIXME
-   // to make this more flexible
-   if (Target->IsOptional())
-     Verify = false;
-   else
-     Verify = true;
-
    Init(Target->URI, Target->Description, Target->ShortDesc);
    Init(Target->URI, Target->Description, Target->ShortDesc);
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1008,6 +1154,7 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &S
    else
    else
    {
    {
       Desc.URI = URI + '.' + comprExt;
       Desc.URI = URI + '.' + comprExt;
+      DestFile = DestFile + '.' + comprExt;
       if(Target)
       if(Target)
          MetaKey = string(Target->MetaKey) + '.' + comprExt;
          MetaKey = string(Target->MetaKey) + '.' + comprExt;
    }
    }
@@ -1018,6 +1165,8 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &S
       indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
       indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
       if(Record)
       if(Record)
          FileSize = Record->Size;
          FileSize = Record->Size;
+      
+      InitByHashIfNeeded(MetaKey);
    }
    }
 
 
    Desc.Description = URIDesc;
    Desc.Description = URIDesc;
@@ -1027,21 +1176,51 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &S
    QueueURI(Desc);
    QueueURI(Desc);
 }
 }
 									/*}}}*/
 									/*}}}*/
+// AcqIndex::AdjustForByHash - modify URI for by-hash support		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey)
+{
+   // TODO:
+   //  - (maybe?) add support for by-hash into the sources.list as flag
+   //  - make apt-ftparchive generate the hashes (and expire?)
+   std::string HostKnob = "APT::Acquire::" + ::URI(Desc.URI).Host + "::By-Hash";
+   if(_config->FindB("APT::Acquire::By-Hash", false) == true ||
+      _config->FindB(HostKnob, false) == true ||
+      MetaIndexParser->GetSupportsAcquireByHash())
+   {
+      indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
+      if(Record)
+      {
+         // FIXME: should we really use the best hash here? or a fixed one?
+         const HashString *TargetHash = Record->Hashes.find("");
+         std::string ByHash = "/by-hash/" + TargetHash->HashType() + "/" + TargetHash->HashValue();
+         size_t trailing_slash = Desc.URI.find_last_of("/");
+         Desc.URI = Desc.URI.replace(
+            trailing_slash,
+            Desc.URI.substr(trailing_slash+1).size()+1,
+            ByHash);
+      } else {
+         _error->Warning(
+            "Fetching ByHash requested but can not find record for %s",
+            MetaKey.c_str());
+      }
+   }
+}
+									/*}}}*/
 // AcqIndex::Custom600Headers - Insert custom request headers		/*{{{*/
 // AcqIndex::Custom600Headers - Insert custom request headers		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* The only header we use is the last-modified header. */
 /* The only header we use is the last-modified header. */
 string pkgAcqIndex::Custom600Headers() const
 string pkgAcqIndex::Custom600Headers() const
 {
 {
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
    string Final = _config->FindDir("Dir::State::lists");
    string Final = _config->FindDir("Dir::State::lists");
    Final += URItoFileName(RealURI);
    Final += URItoFileName(RealURI);
    if (_config->FindB("Acquire::GzipIndexes",false))
    if (_config->FindB("Acquire::GzipIndexes",false))
-      Final += ".gz";
+      Final += compExt;
    
    
    string msg = "\nIndex-File: true";
    string msg = "\nIndex-File: true";
-   // FIXME: this really should use "IndexTarget::IsOptional()" but that
-   //        seems to be difficult without breaking ABI
-   if (ShortDesc().find("Translation") != 0)
-      msg += "\nFail-Ignore: true";
+
    struct stat Buf;
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) == 0)
    if (stat(Final.c_str(),&Buf) == 0)
       msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
       msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
@@ -1069,6 +1248,31 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
    Item::Failed(Message,Cnf);
    Item::Failed(Message,Cnf);
 }
 }
 									/*}}}*/
 									/*}}}*/
+// pkgAcqIndex::GetFinalFilename - Return the full final file path      /*{{{*/
+std::string pkgAcqIndex::GetFinalFilename(std::string const &URI,
+                                          std::string const &compExt)
+{
+   std::string FinalFile = _config->FindDir("Dir::State::lists");
+   FinalFile += URItoFileName(URI);
+   if (_config->FindB("Acquire::GzipIndexes",false) == true)
+      FinalFile += '.' + compExt;
+   return FinalFile;
+}
+									/*}}}*/
+// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit		/*{{{*/
+void pkgAcqIndex::ReverifyAfterIMS(std::string const &FileName)
+{
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
+   if (_config->FindB("Acquire::GzipIndexes",false) == true)
+      DestFile += compExt;
+
+   string FinalFile = GetFinalFilename(RealURI, compExt);
+   Rename(FinalFile, FileName);
+   Decompression = true;
+   Desc.URI = "copy:" + FileName;
+   QueueURI(Desc);
+}
+									/*}}}*/
 // AcqIndex::Done - Finished a fetch					/*{{{*/
 // AcqIndex::Done - Finished a fetch					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This goes through a number of states.. On the initial fetch the
 /* This goes through a number of states.. On the initial fetch the
@@ -1080,39 +1284,41 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
 		       pkgAcquire::MethodConfig *Cfg)
 		       pkgAcquire::MethodConfig *Cfg)
 {
 {
    Item::Done(Message,Size,Hashes,Cfg);
    Item::Done(Message,Size,Hashes,Cfg);
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
 
 
    if (Decompression == true)
    if (Decompression == true)
    {
    {
       if (ExpectedHashes.usable() && ExpectedHashes != Hashes)
       if (ExpectedHashes.usable() && ExpectedHashes != Hashes)
       {
       {
+         Desc.URI = RealURI;
 	 RenameOnError(HashSumMismatch);
 	 RenameOnError(HashSumMismatch);
 	 printHashSumComparision(RealURI, ExpectedHashes, Hashes);
 	 printHashSumComparision(RealURI, ExpectedHashes, Hashes);
          return;
          return;
       }
       }
 
 
-      /* Verify the index file for correctness (all indexes must
-       * have a Package field) (LP: #346386) (Closes: #627642) */
-      if (Verify == true)
+      // FIXME: this can go away once we only ever download stuff that
+      //        has a valid hash and we never do GET based probing
+      //
+      /* Always verify the index file for correctness (all indexes must
+       * have a Package field) (LP: #346386) (Closes: #627642) 
+       */
+      FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Extension);
+      // Only test for correctness if the file is not empty (empty is ok)
+      if (fd.Size() > 0)
       {
       {
-	 FileFd fd(DestFile, FileFd::ReadOnly);
-	 // Only test for correctness if the file is not empty (empty is ok)
-	 if (fd.FileSize() > 0)
-	 {
-	    pkgTagSection sec;
-	    pkgTagFile tag(&fd);
-
-	    // all our current indexes have a field 'Package' in each section
-	    if (_error->PendingError() == true || tag.Step(sec) == false || sec.Exists("Package") == false)
-	    {
-	       RenameOnError(InvalidFormat);
-	       return;
-	    }
+         pkgTagSection sec;
+         pkgTagFile tag(&fd);
+         
+         // all our current indexes have a field 'Package' in each section
+         if (_error->PendingError() == true || tag.Step(sec) == false || sec.Exists("Package") == false)
+         {
+            RenameOnError(InvalidFormat);
+            return;
          }
          }
       }
       }
        
        
       // Done, move it into position
       // Done, move it into position
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
+      string FinalFile = GetFinalFilename(RealURI, compExt);
       Rename(DestFile,FinalFile);
       Rename(DestFile,FinalFile);
       chmod(FinalFile.c_str(),0644);
       chmod(FinalFile.c_str(),0644);
 
 
@@ -1120,7 +1326,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
          will work OK */
          will work OK */
       DestFile = _config->FindDir("Dir::State::lists") + "partial/";
       DestFile = _config->FindDir("Dir::State::lists") + "partial/";
       DestFile += URItoFileName(RealURI);
       DestFile += URItoFileName(RealURI);
-      
+      if (_config->FindB("Acquire::GzipIndexes",false))
+         DestFile += '.' + compExt;
+
       // Remove the compressed version.
       // Remove the compressed version.
       if (Erase == true)
       if (Erase == true)
 	 unlink(DestFile.c_str());
 	 unlink(DestFile.c_str());
@@ -1135,15 +1343,20 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
    string FileName = LookupTag(Message,"Alt-Filename");
    string FileName = LookupTag(Message,"Alt-Filename");
    if (FileName.empty() == false)
    if (FileName.empty() == false)
    {
    {
-      // The files timestamp matches
-      if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
-	 return;
       Decompression = true;
       Decompression = true;
       Local = true;
       Local = true;
       DestFile += ".decomp";
       DestFile += ".decomp";
       Desc.URI = "copy:" + FileName;
       Desc.URI = "copy:" + FileName;
       QueueURI(Desc);
       QueueURI(Desc);
+      ActiveSubprocess = "copy";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
       Mode = "copy";
       Mode = "copy";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
       return;
       return;
    }
    }
 
 
@@ -1154,33 +1367,44 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
       ErrorText = "Method gave a blank filename";
       ErrorText = "Method gave a blank filename";
    }
    }
 
 
-   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
-
-   // The files timestamp matches
-   if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) {
-       if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
-	  // Update DestFile for .gz suffix so that the clean operation keeps it
-	  DestFile += ".gz";
-      return;
-    }
-
    if (FileName == DestFile)
    if (FileName == DestFile)
       Erase = true;
       Erase = true;
    else
    else
       Local = true;
       Local = true;
-   
+
+   // do not reverify cdrom sources as apt-cdrom may rewrite the Packages
+   // file when its doing the indexcopy
+   if (RealURI.substr(0,6) == "cdrom:" &&
+       StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+      return;
+
+   // The files timestamp matches, for non-local URLs reverify the local
+   // file, for local file, uncompress again to ensure the hashsum is still
+   // matching the Release file
+   if (!Local && StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+   {
+      // set destfile to the final destfile
+      if(_config->FindB("Acquire::GzipIndexes",false) == false)
+      {
+         DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+         DestFile += URItoFileName(RealURI);
+      }
+
+      ReverifyAfterIMS(FileName);
+      return;
+   }
    string decompProg;
    string decompProg;
 
 
-   // If we enable compressed indexes and already have gzip, keep it
-   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) {
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI) + ".gz";
-      Rename(DestFile,FinalFile);
-      chmod(FinalFile.c_str(),0644);
-      
-      // Update DestFile for .gz suffix so that the clean operation keeps it
-      DestFile = _config->FindDir("Dir::State::lists") + "partial/";
-      DestFile += URItoFileName(RealURI) + ".gz";
+   // If we enable compressed indexes, queue for hash verification
+   if (_config->FindB("Acquire::GzipIndexes",false))
+   {
+      DestFile = _config->FindDir("Dir::State::lists");
+      DestFile += URItoFileName(RealURI) + '.' + compExt;
+
+      Decompression = true;
+      Desc.URI = "copy:" + FileName;
+      QueueURI(Desc);
+
       return;
       return;
     }
     }
 
 
@@ -1199,8 +1423,15 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
    Desc.URI = decompProg + ":" + FileName;
    Desc.URI = decompProg + ":" + FileName;
    QueueURI(Desc);
    QueueURI(Desc);
 
 
-   // FIXME: this points to a c++ string that goes out of scope
-   Mode = decompProg.c_str();
+   ActiveSubprocess = decompProg;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+      Mode = ActiveSubprocess.c_str();
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 }
 }
 									/*}}}*/
 									/*}}}*/
 // AcqIndexTrans::pkgAcqIndexTrans - Constructor			/*{{{*/
 // AcqIndexTrans::pkgAcqIndexTrans - Constructor			/*{{{*/
@@ -1225,8 +1456,11 @@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const * const
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 string pkgAcqIndexTrans::Custom600Headers() const
 string pkgAcqIndexTrans::Custom600Headers() const
 {
 {
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
    string Final = _config->FindDir("Dir::State::lists");
    string Final = _config->FindDir("Dir::State::lists");
    Final += URItoFileName(RealURI);
    Final += URItoFileName(RealURI);
+   if (_config->FindB("Acquire::GzipIndexes",false))
+      Final += compExt;
 
 
    struct stat Buf;
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
    if (stat(Final.c_str(),&Buf) != 0)
@@ -1499,7 +1733,15 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,HashStringList
          AuthPass = true;
          AuthPass = true;
          Desc.URI = "gpgv:" + SigFile;
          Desc.URI = "gpgv:" + SigFile;
          QueueURI(Desc);
          QueueURI(Desc);
-         Mode = "gpgv";
+	 ActiveSubprocess = "gpgv";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	 Mode = "gpgv";
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 	 return;
 	 return;
       }
       }
    }
    }
@@ -1580,6 +1822,32 @@ void pkgAcqMetaIndex::AuthDone(string Message)				/*{{{*/
       std::cerr << "Signature verification succeeded: "
       std::cerr << "Signature verification succeeded: "
                 << DestFile << std::endl;
                 << DestFile << std::endl;
 
 
+   // do not trust any previously unverified content that we may have
+   string LastGoodSigFile = _config->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI));
+   if (DestFile != SigFile)
+      LastGoodSigFile.append(".gpg");
+   LastGoodSigFile.append(".reverify");
+   if(IMSHit == false && RealFileExists(LastGoodSigFile) == false)
+   {
+      for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
+           Target != IndexTargets->end();
+           ++Target)
+      {
+         // remove old indexes
+         std::string index = _config->FindDir("Dir::State::lists") +
+            URItoFileName((*Target)->URI);
+         unlink(index.c_str());
+         // and also old gzipindexes
+         std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+         for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+         {
+            index += '.' + (*t);
+            unlink(index.c_str());
+         }
+      }
+   }
+
+
    // Download further indexes with verification
    // Download further indexes with verification
    QueueIndexes(true);
    QueueIndexes(true);
 
 

+ 47 - 36
apt-pkg/acquire-item.h

@@ -133,7 +133,12 @@ class pkgAcquire::Item : public WeakPointable
    /** \brief If not \b NULL, contains the name of a subprocess that
    /** \brief If not \b NULL, contains the name of a subprocess that
     *  is operating on this object (for instance, "gzip" or "gpgv").
     *  is operating on this object (for instance, "gzip" or "gpgv").
     */
     */
-   const char *Mode;
+   APT_DEPRECATED const char *Mode;
+
+   /** \brief contains the name of the subprocess that is operating on this object
+    * (for instance, "gzip", "rred" or "gpgv"). This is obsoleting #Mode from above
+    * as it can manage the lifetime of included string properly. */
+   std::string ActiveSubprocess;
 
 
    /** \brief A client-supplied unique identifier.
    /** \brief A client-supplied unique identifier.
     * 
     * 
@@ -245,12 +250,12 @@ class pkgAcquire::Item : public WeakPointable
     *
     *
     *  \return a URI that should be used to describe what is being fetched.
     *  \return a URI that should be used to describe what is being fetched.
     */
     */
-   virtual std::string DescURI() const = 0;
+   virtual std::string DescURI() = 0;
    /** \brief Short item description.
    /** \brief Short item description.
     *
     *
     *  \return a brief description of the object being fetched.
     *  \return a brief description of the object being fetched.
     */
     */
-   virtual std::string ShortDesc() const {return DescURI();}
+   virtual std::string ShortDesc() {return DescURI();}
 
 
    /** \brief Invoked by the worker when the download is completely done. */
    /** \brief Invoked by the worker when the download is completely done. */
    virtual void Finished() {};
    virtual void Finished() {};
@@ -289,7 +294,8 @@ class pkgAcquire::Item : public WeakPointable
     *  \param Owner The new owner of this item.
     *  \param Owner The new owner of this item.
     *  \param ExpectedHashes of the file represented by this item
     *  \param ExpectedHashes of the file represented by this item
     */
     */
-   Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes);
+   Item(pkgAcquire *Owner,
+        HashStringList const &ExpectedHashes=HashStringList());
 
 
    /** \brief Remove this item from its owner's queue by invoking
    /** \brief Remove this item from its owner's queue by invoking
     *  pkgAcquire::Remove.
     *  pkgAcquire::Remove.
@@ -322,11 +328,17 @@ struct DiffInfo {
    /** The filename of the diff. */
    /** The filename of the diff. */
    std::string file;
    std::string file;
 
 
-   /** The sha1 hash of the diff. */
-   std::string sha1;
+   /** The hashes of the diff */
+   HashStringList result_hashes;
+
+   /** The hashes of the file after the diff is applied */
+   HashStringList patch_hashes;
+
+   /** The size of the file after the diff is applied */
+   unsigned long long result_size;
 
 
-   /** The size of the diff. */
-   unsigned long size;
+   /** The size of the diff itself */
+   unsigned long long patch_size;
 };
 };
 									/*}}}*/
 									/*}}}*/
 /** \brief An item that is responsible for fetching a SubIndex		{{{
 /** \brief An item that is responsible for fetching a SubIndex		{{{
@@ -346,7 +358,7 @@ class pkgAcqSubIndex : public pkgAcquire::Item
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() const {return Desc.URI;};
+   virtual std::string DescURI() {return Desc.URI;};
    virtual std::string Custom600Headers() const;
    virtual std::string Custom600Headers() const;
    virtual bool ParseIndex(std::string const &IndexFile);
    virtual bool ParseIndex(std::string const &IndexFile);
 
 
@@ -422,7 +434,7 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() const {return RealURI + "Index";};
+   virtual std::string DescURI() {return RealURI + "Index";};
    virtual std::string Custom600Headers() const;
    virtual std::string Custom600Headers() const;
 
 
    /** \brief Parse the Index file for a set of Packages diffs.
    /** \brief Parse the Index file for a set of Packages diffs.
@@ -515,7 +527,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 	 pkgAcquire::MethodConfig *Cnf);
 	 pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() const {return RealURI + "Index";};
+   virtual std::string DescURI() {return RealURI + "Index";};
 
 
    /** \brief Create an index merge-diff item.
    /** \brief Create an index merge-diff item.
     *
     *
@@ -570,7 +582,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     *  \return \b true if an applicable diff was found, \b false
     *  \return \b true if an applicable diff was found, \b false
     *  otherwise.
     *  otherwise.
     */
     */
-   bool QueueNextDiff();
+   APT_HIDDEN bool QueueNextDiff();
 
 
    /** \brief Handle tasks that must be performed after the item
    /** \brief Handle tasks that must be performed after the item
     *  finishes downloading.
     *  finishes downloading.
@@ -583,7 +595,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     *  \param allDone If \b true, the file was entirely reconstructed,
     *  \param allDone If \b true, the file was entirely reconstructed,
     *  and its md5sum is verified. 
     *  and its md5sum is verified. 
     */
     */
-   void Finish(bool allDone=false);
+   APT_HIDDEN void Finish(bool allDone=false);
 
 
    protected:
    protected:
 
 
@@ -610,9 +622,6 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     */
     */
    std::vector<DiffInfo> available_patches;
    std::vector<DiffInfo> available_patches;
 
 
-   /** Stop applying patches when reaching that sha1 */
-   std::string ServerSha1;
-
    /** The current status of this patch. */
    /** The current status of this patch. */
    enum DiffState
    enum DiffState
      {
      {
@@ -640,7 +649,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
 
 
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() const {return RealURI + "Index";};
+   virtual std::string DescURI() {return RealURI + "Index";};
 
 
    /** \brief Create an index diff item.
    /** \brief Create an index diff item.
     *
     *
@@ -656,12 +665,10 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     *
     *
     *  \param ShortDesc A brief description of this item.
     *  \param ShortDesc A brief description of this item.
     *
     *
-    *  \param ExpectedHashes The expected md5sum of the completely
+    *  \param ExpectedHashes The expected hashsums of the completely
     *  reconstructed package index file; the index file will be tested
     *  reconstructed package index file; the index file will be tested
     *  against this value when it is entirely reconstructed.
     *  against this value when it is entirely reconstructed.
     *
     *
-    *  \param ServerSha1 is the sha1sum of the current file on the server
-    *
     *  \param diffs The remaining diffs from the index of diffs.  They
     *  \param diffs The remaining diffs from the index of diffs.  They
     *  should be ordered so that each diff appears before any diff
     *  should be ordered so that each diff appears before any diff
     *  that depends on it.
     *  that depends on it.
@@ -670,7 +677,6 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
                     struct IndexTarget const * const Target,
                     struct IndexTarget const * const Target,
                     HashStringList const &ExpectedHash,
                     HashStringList const &ExpectedHash,
                     indexRecords *MetaIndexParser,
                     indexRecords *MetaIndexParser,
-		    std::string ServerSha1,
 		    std::vector<DiffInfo> diffs=std::vector<DiffInfo>());
 		    std::vector<DiffInfo> diffs=std::vector<DiffInfo>());
 };
 };
 									/*}}}*/
 									/*}}}*/
@@ -693,15 +699,8 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     */
     */
    bool Erase;
    bool Erase;
 
 
-   /** \brief Verify for correctness by checking if a "Package"
-    *         tag is found in the index. This can be set to
-    *         false for optional index targets
-    *       
-    */
-   // FIXME: instead of a bool it should use a verify string that will
-   //        then be used in the pkgAcqIndex::Done method to ensure that
-   //        the downloaded file contains the expected tag
-   bool Verify;
+   // Unused, used to be used to verify that "Packages: " header was there
+   bool __DELME_ON_NEXT_ABI_BREAK_Verify;
 
 
    /** \brief The object that is actually being fetched (minus any
    /** \brief The object that is actually being fetched (minus any
     *  compression-related extensions).
     *  compression-related extensions).
@@ -713,6 +712,18 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     */
     */
    std::string CompressionExtension;
    std::string CompressionExtension;
 
 
+
+   /** \brief Do the changes needed to fetch via AptByHash (if needed) */
+   void InitByHashIfNeeded(const std::string MetaKey);
+
+   /** \brief Get the full pathname of the final file for the given URI
+    */
+   std::string GetFinalFilename(std::string const &URI,
+                                std::string const &compExt);
+
+   /** \brief Schedule file for verification after a IMS hit */
+   void ReverifyAfterIMS(std::string const &FileName);
+
    public:
    public:
    
    
    // Specialized action members
    // Specialized action members
@@ -720,7 +731,7 @@ class pkgAcqIndex : public pkgAcqBaseIndex
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
    virtual std::string Custom600Headers() const;
    virtual std::string Custom600Headers() const;
-   virtual std::string DescURI() const {return Desc.URI;};
+   virtual std::string DescURI() {return Desc.URI;};
 
 
    /** \brief Create a pkgAcqIndex.
    /** \brief Create a pkgAcqIndex.
     *
     *
@@ -884,7 +895,7 @@ class pkgAcqMetaSig : public pkgAcquire::Item
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
    virtual std::string Custom600Headers() const;
    virtual std::string Custom600Headers() const;
-   virtual std::string DescURI() const {return RealURI; };
+   virtual std::string DescURI() {return RealURI; };
 
 
    /** \brief Create a new pkgAcqMetaSig. */
    /** \brief Create a new pkgAcqMetaSig. */
    pkgAcqMetaSig(pkgAcquire *Owner,std::string URI,std::string URIDesc, std::string ShortDesc,
    pkgAcqMetaSig(pkgAcquire *Owner,std::string URI,std::string URIDesc, std::string ShortDesc,
@@ -977,7 +988,7 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
    virtual std::string Custom600Headers() const;
    virtual std::string Custom600Headers() const;
-   virtual std::string DescURI() const {return RealURI; };
+   virtual std::string DescURI() {return RealURI; };
 
 
    /** \brief Create a new pkgAcqMetaIndex. */
    /** \brief Create a new pkgAcqMetaIndex. */
    pkgAcqMetaIndex(pkgAcquire *Owner,
    pkgAcqMetaIndex(pkgAcquire *Owner,
@@ -1071,8 +1082,8 @@ class pkgAcqArchive : public pkgAcquire::Item
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() const {return Desc.URI;};
-   virtual std::string ShortDesc() const {return Desc.ShortDesc;};
+   virtual std::string DescURI() {return Desc.URI;};
+   virtual std::string ShortDesc() {return Desc.ShortDesc;};
    virtual void Finished();
    virtual void Finished();
    virtual bool IsTrusted() const;
    virtual bool IsTrusted() const;
    
    
@@ -1121,7 +1132,7 @@ class pkgAcqFile : public pkgAcquire::Item
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &CalcHashes,
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &CalcHashes,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() const {return Desc.URI;};
+   virtual std::string DescURI() {return Desc.URI;};
    virtual std::string Custom600Headers() const;
    virtual std::string Custom600Headers() const;
 
 
    /** \brief Create a new pkgAcqFile object.
    /** \brief Create a new pkgAcqFile object.

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

@@ -118,6 +118,18 @@ void pkgAcqMethod::Fail(string Err,bool Transient)
 
 
    std::cout << "\n" << std::flush;
    std::cout << "\n" << std::flush;
 }
 }
+									/*}}}*/
+// AcqMethod::DropPrivsOrDie - Drop privileges or die		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMethod::DropPrivsOrDie()
+{
+   if (!DropPrivs()) {
+      Fail(false);
+      exit(112);	/* call the european emergency number */
+   }
+}
+
 									/*}}}*/
 									/*}}}*/
 // AcqMethod::URIStart - Indicate a download is starting		/*{{{*/
 // AcqMethod::URIStart - Indicate a download is starting		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------

+ 1 - 1
apt-pkg/acquire-method.h

@@ -106,7 +106,7 @@ class pkgAcqMethod
    
    
    pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
    pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
    virtual ~pkgAcqMethod() {};
    virtual ~pkgAcqMethod() {};
-
+   void DropPrivsOrDie();
    private:
    private:
    APT_HIDDEN void Dequeue();
    APT_HIDDEN void Dequeue();
 };
 };

+ 26 - 28
apt-pkg/acquire.cc

@@ -73,23 +73,27 @@ pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) :  LockFD(-1), Queues(0), Wor
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Do everything needed to be a complete Acquire object and report the
 /* Do everything needed to be a complete Acquire object and report the
    success (or failure) back so the user knows that something is wrong… */
    success (or failure) back so the user knows that something is wrong… */
-bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock)
+bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock,
+      bool const createDirectories)
 {
 {
    Log = Progress;
    Log = Progress;
 
 
    // check for existence and possibly create auxiliary directories
    // check for existence and possibly create auxiliary directories
-   string const listDir = _config->FindDir("Dir::State::lists");
-   string const partialListDir = listDir + "partial/";
-   string const archivesDir = _config->FindDir("Dir::Cache::Archives");
-   string const partialArchivesDir = archivesDir + "partial/";
-
-   if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
-       CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false)
-      return _error->Errno("Acquire", _("List directory %spartial is missing."), listDir.c_str());
-
-   if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::Cache"), partialArchivesDir) == false &&
-       CreateAPTDirectoryIfNeeded(archivesDir, partialArchivesDir) == false)
-      return _error->Errno("Acquire", _("Archives directory %spartial is missing."), archivesDir.c_str());
+   if (createDirectories == true)
+   {
+      string const listDir = _config->FindDir("Dir::State::lists");
+      string const partialListDir = listDir + "partial/";
+      string const archivesDir = _config->FindDir("Dir::Cache::Archives");
+      string const partialArchivesDir = archivesDir + "partial/";
+
+      if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
+	    CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false)
+	 return _error->Errno("Acquire", _("List directory %spartial is missing."), listDir.c_str());
+
+      if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::Cache"), partialArchivesDir) == false &&
+	    CreateAPTDirectoryIfNeeded(archivesDir, partialArchivesDir) == false)
+	 return _error->Errno("Acquire", _("Archives directory %spartial is missing."), archivesDir.c_str());
+   }
 
 
    if (Lock.empty() == true || _config->FindB("Debug::NoLocking", false) == true)
    if (Lock.empty() == true || _config->FindB("Debug::NoLocking", false) == true)
       return true;
       return true;
@@ -487,6 +491,9 @@ bool pkgAcquire::Clean(string Dir)
    if (DirectoryExists(Dir) == false)
    if (DirectoryExists(Dir) == false)
       return true;
       return true;
 
 
+   if(Dir == "/")
+      return _error->Error(_("Clean of %s is not supported"), Dir.c_str());
+
    DIR *D = opendir(Dir.c_str());   
    DIR *D = opendir(Dir.c_str());   
    if (D == 0)
    if (D == 0)
       return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
       return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
@@ -578,27 +585,18 @@ pkgAcquire::UriIterator pkgAcquire::UriEnd()
 // Acquire::MethodConfig::MethodConfig - Constructor			/*{{{*/
 // Acquire::MethodConfig::MethodConfig - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgAcquire::MethodConfig::MethodConfig()
+pkgAcquire::MethodConfig::MethodConfig() : d(NULL), Next(0), SingleInstance(false),
+   Pipeline(false), SendConfig(false), LocalOnly(false), NeedsCleanup(false),
+   Removable(false)
 {
 {
-   SingleInstance = false;
-   Pipeline = false;
-   SendConfig = false;
-   LocalOnly = false;
-   Removable = false;
-   Next = 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Queue::Queue - Constructor						/*{{{*/
 // Queue::Queue - Constructor						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgAcquire::Queue::Queue(string Name,pkgAcquire *Owner) : Name(Name), 
-            Owner(Owner)
+pkgAcquire::Queue::Queue(string Name,pkgAcquire *Owner) : d(NULL), Next(0),
+   Name(Name), Items(0), Workers(0), Owner(Owner), PipeDepth(0), MaxPipeDepth(1)
 {
 {
-   Items = 0;
-   Next = 0;
-   Workers = 0;
-   MaxPipeDepth = 1;
-   PipeDepth = 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Queue::~Queue - Destructor						/*{{{*/
 // Queue::~Queue - Destructor						/*{{{*/
@@ -802,7 +800,7 @@ void pkgAcquire::Queue::Bump()
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Update(true), MorePulses(false)
+pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(0), Update(true), MorePulses(false)
 {
 {
    Start();
    Start();
 }
 }

+ 5 - 2
apt-pkg/acquire.h

@@ -352,8 +352,11 @@ class pkgAcquire
     *  \param Lock defines a lock file that should be acquired to ensure
     *  \param Lock defines a lock file that should be acquired to ensure
     *  only one Acquire class is in action at the time or an empty string
     *  only one Acquire class is in action at the time or an empty string
     *  if no lock file should be used.
     *  if no lock file should be used.
+    *  \param createDirectories can be used to disable the creation of directories,
+    *  e.g. if the fetcher is used with different directories later on
     */
     */
-   bool Setup(pkgAcquireStatus *Progress = NULL, std::string const &Lock = "");
+   bool Setup(pkgAcquireStatus *Progress = NULL, std::string const &Lock = "",
+      bool const createDirectories = true);
 
 
    void SetLog(pkgAcquireStatus *Progress) { Log = Progress; }
    void SetLog(pkgAcquireStatus *Progress) { Log = Progress; }
 
 
@@ -585,7 +588,7 @@ class pkgAcquire::UriIterator
     *
     *
     *  \param Q The queue over which this UriIterator should iterate.
     *  \param Q The queue over which this UriIterator should iterate.
     */
     */
-   UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0)
+   UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0)
    {
    {
       while (CurItem == 0 && CurQ != 0)
       while (CurItem == 0 && CurQ != 0)
       {
       {

+ 6 - 10
apt-pkg/algorithms.cc

@@ -640,13 +640,11 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 // ProblemResolver::Resolve - calls a resolver to fix the situation	/*{{{*/
 // ProblemResolver::Resolve - calls a resolver to fix the situation	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-bool pkgProblemResolver::Resolve(bool BrokenFix)
+bool pkgProblemResolver::Resolve(bool BrokenFix, OpProgress * const Progress)
 {
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    std::string const solver = _config->Find("APT::Solver", "internal");
-   if (solver != "internal") {
-      OpTextProgress Prog(*_config);
-      return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false, &Prog);
-   }
+   if (solver != "internal")
+      return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false, Progress);
    return ResolveInternal(BrokenFix);
    return ResolveInternal(BrokenFix);
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1140,13 +1138,11 @@ bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
 /* This is the work horse of the soft upgrade routine. It is very gental 
 /* This is the work horse of the soft upgrade routine. It is very gental 
    in that it does not install or remove any packages. It is assumed that the
    in that it does not install or remove any packages. It is assumed that the
    system was non-broken previously. */
    system was non-broken previously. */
-bool pkgProblemResolver::ResolveByKeep()
+bool pkgProblemResolver::ResolveByKeep(OpProgress * const Progress)
 {
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    std::string const solver = _config->Find("APT::Solver", "internal");
-   if (solver != "internal") {
-      OpTextProgress Prog(*_config);
-      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
-   }
+   if (solver != "internal")
+      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
    return ResolveByKeepInternal();
    return ResolveByKeepInternal();
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 14 - 14
apt-pkg/algorithms.h

@@ -82,9 +82,9 @@ class pkgSimulate : public pkgPackageManager				/*{{{*/
    virtual bool Remove(PkgIterator Pkg,bool Purge);
    virtual bool Remove(PkgIterator Pkg,bool Purge);
 
 
 private:
 private:
-   void ShortBreaks();
-   void Describe(PkgIterator iPkg,std::ostream &out,bool Current,bool Candidate);
-   
+   APT_HIDDEN void ShortBreaks();
+   APT_HIDDEN void Describe(PkgIterator iPkg,std::ostream &out,bool Current,bool Candidate);
+
    public:
    public:
 
 
    pkgSimulate(pkgDepCache *Cache);
    pkgSimulate(pkgDepCache *Cache);
@@ -114,7 +114,7 @@ class pkgProblemResolver						/*{{{*/
    
    
    // Sort stuff
    // Sort stuff
    static pkgProblemResolver *This;
    static pkgProblemResolver *This;
-   static int ScoreSort(const void *a,const void *b) APT_PURE;
+   APT_HIDDEN static int ScoreSort(const void *a,const void *b) APT_PURE;
 
 
    struct PackageKill
    struct PackageKill
    {
    {
@@ -122,12 +122,12 @@ class pkgProblemResolver						/*{{{*/
       DepIterator Dep;
       DepIterator Dep;
    };
    };
 
 
-   void MakeScores();
-   bool DoUpgrade(pkgCache::PkgIterator Pkg);
+   APT_HIDDEN void MakeScores();
+   APT_HIDDEN bool DoUpgrade(pkgCache::PkgIterator Pkg);
+
+   APT_HIDDEN bool ResolveInternal(bool const BrokenFix = false);
+   APT_HIDDEN bool ResolveByKeepInternal();
 
 
-   bool ResolveInternal(bool const BrokenFix = false);
-   bool ResolveByKeepInternal();
-   
    protected:
    protected:
    bool InstOrNewPolicyBroken(pkgCache::PkgIterator Pkg);
    bool InstOrNewPolicyBroken(pkgCache::PkgIterator Pkg);
 
 
@@ -136,12 +136,12 @@ class pkgProblemResolver						/*{{{*/
    inline void Protect(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= Protected; Cache.MarkProtected(Pkg);};
    inline void Protect(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= Protected; Cache.MarkProtected(Pkg);};
    inline void Remove(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= ToRemove;};
    inline void Remove(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= ToRemove;};
    inline void Clear(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] &= ~(Protected | ToRemove);};
    inline void Clear(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] &= ~(Protected | ToRemove);};
-   
-   // Try to intelligently resolve problems by installing and removing packages   
-   bool Resolve(bool BrokenFix = false);
-   
+
+   // Try to intelligently resolve problems by installing and removing packages
+   bool Resolve(bool BrokenFix = false, OpProgress * const Progress = NULL);
+
    // Try to resolve problems only by using keep
    // Try to resolve problems only by using keep
-   bool ResolveByKeep();
+   bool ResolveByKeep(OpProgress * const Progress = NULL);
 
 
    APT_DEPRECATED void InstallProtect();
    APT_DEPRECATED void InstallProtect();
 
 

+ 29 - 29
apt-pkg/aptconfiguration.cc

@@ -32,6 +32,35 @@
 #include <apti18n.h>
 #include <apti18n.h>
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
+// setDefaultConfigurationForCompressors				/*{{{*/
+static void setDefaultConfigurationForCompressors() {
+	// Set default application paths to check for optional compression types
+	_config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
+	_config->CndSet("Dir::Bin::xz", "/usr/bin/xz");
+	if (FileExists(_config->FindFile("Dir::Bin::xz")) == true) {
+		_config->Set("Dir::Bin::lzma", _config->FindFile("Dir::Bin::xz"));
+		_config->Set("APT::Compressor::lzma::Binary", "xz");
+		if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
+			_config->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");
+			_config->Set("APT::Compressor::lzma::CompressArg::", "-9");
+		}
+		if (_config->Exists("APT::Compressor::lzma::UncompressArg") == false) {
+			_config->Set("APT::Compressor::lzma::UncompressArg::", "--format=lzma");
+			_config->Set("APT::Compressor::lzma::UncompressArg::", "-d");
+		}
+	} else {
+		_config->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
+		if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
+			_config->Set("APT::Compressor::lzma::CompressArg::", "--suffix=");
+			_config->Set("APT::Compressor::lzma::CompressArg::", "-9");
+		}
+		if (_config->Exists("APT::Compressor::lzma::UncompressArg") == false) {
+			_config->Set("APT::Compressor::lzma::UncompressArg::", "--suffix=");
+			_config->Set("APT::Compressor::lzma::UncompressArg::", "-d");
+		}
+	}
+}
+									/*}}}*/
 // getCompressionTypes - Return Vector of usable compressiontypes	/*{{{*/
 // getCompressionTypes - Return Vector of usable compressiontypes	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* return a vector of compression types in the preferred order. */
 /* return a vector of compression types in the preferred order. */
@@ -402,35 +431,6 @@ bool Configuration::checkArchitecture(std::string const &Arch) {
 	return (std::find(archs.begin(), archs.end(), Arch) != archs.end());
 	return (std::find(archs.begin(), archs.end(), Arch) != archs.end());
 }
 }
 									/*}}}*/
 									/*}}}*/
-// setDefaultConfigurationForCompressors				/*{{{*/
-void Configuration::setDefaultConfigurationForCompressors() {
-	// Set default application paths to check for optional compression types
-	_config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
-	_config->CndSet("Dir::Bin::xz", "/usr/bin/xz");
-	if (FileExists(_config->FindFile("Dir::Bin::xz")) == true) {
-		_config->Set("Dir::Bin::lzma", _config->FindFile("Dir::Bin::xz"));
-		_config->Set("APT::Compressor::lzma::Binary", "xz");
-		if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
-			_config->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");
-			_config->Set("APT::Compressor::lzma::CompressArg::", "-9");
-		}
-		if (_config->Exists("APT::Compressor::lzma::UncompressArg") == false) {
-			_config->Set("APT::Compressor::lzma::UncompressArg::", "--format=lzma");
-			_config->Set("APT::Compressor::lzma::UncompressArg::", "-d");
-		}
-	} else {
-		_config->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
-		if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
-			_config->Set("APT::Compressor::lzma::CompressArg::", "--suffix=");
-			_config->Set("APT::Compressor::lzma::CompressArg::", "-9");
-		}
-		if (_config->Exists("APT::Compressor::lzma::UncompressArg") == false) {
-			_config->Set("APT::Compressor::lzma::UncompressArg::", "--suffix=");
-			_config->Set("APT::Compressor::lzma::UncompressArg::", "-d");
-		}
-	}
-}
-									/*}}}*/
 // getCompressors - Return Vector of usealbe compressors		/*{{{*/
 // getCompressors - Return Vector of usealbe compressors		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* return a vector of compressors used by apt-ftparchive in the
 /* return a vector of compressors used by apt-ftparchive in the

+ 0 - 3
apt-pkg/aptconfiguration.h

@@ -123,9 +123,6 @@ public:									/*{{{*/
 	/** \return Return a comma-separated list of enabled build profile specifications */
 	/** \return Return a comma-separated list of enabled build profile specifications */
 	std::string static const getBuildProfilesString();
 	std::string static const getBuildProfilesString();
 									/*}}}*/
 									/*}}}*/
-	private:							/*{{{*/
-	void static setDefaultConfigurationForCompressors();
-									/*}}}*/
 };
 };
 									/*}}}*/
 									/*}}}*/
 }
 }

+ 3 - 0
apt-pkg/cachefile.cc

@@ -143,6 +143,9 @@ bool pkgCacheFile::BuildDepCache(OpProgress *Progress)
    if (DCache != NULL)
    if (DCache != NULL)
       return true;
       return true;
 
 
+   if (BuildPolicy(Progress) == false)
+      return false;
+
    DCache = new pkgDepCache(Cache,Policy);
    DCache = new pkgDepCache(Cache,Policy);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;

+ 119 - 25
apt-pkg/cachefilter.cc

@@ -6,6 +6,7 @@
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <config.h>
 #include <config.h>
 
 
+#include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefilter.h>
 #include <apt-pkg/cachefilter.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
@@ -22,7 +23,11 @@
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 namespace CacheFilter {
 namespace CacheFilter {
-PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d(NULL) {/*{{{*/
+APT_CONST Matcher::~Matcher() {}
+APT_CONST PackageMatcher::~PackageMatcher() {}
+
+// Name matches RegEx							/*{{{*/
+PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) {
 	pattern = new regex_t;
 	pattern = new regex_t;
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	if (Res == 0)
 	if (Res == 0)
@@ -34,41 +39,36 @@ PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d
 	regerror(Res, pattern, Error, sizeof(Error));
 	regerror(Res, pattern, Error, sizeof(Error));
 	_error->Error(_("Regex compilation error - %s"), Error);
 	_error->Error(_("Regex compilation error - %s"), Error);
 }
 }
-									/*}}}*/
-bool PackageNameMatchesRegEx::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+bool PackageNameMatchesRegEx::operator() (pkgCache::PkgIterator const &Pkg) {
 	if (unlikely(pattern == NULL))
 	if (unlikely(pattern == NULL))
 		return false;
 		return false;
 	else
 	else
 		return regexec(pattern, Pkg.Name(), 0, 0, 0) == 0;
 		return regexec(pattern, Pkg.Name(), 0, 0, 0) == 0;
 }
 }
-									/*}}}*/
-bool PackageNameMatchesRegEx::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/
+bool PackageNameMatchesRegEx::operator() (pkgCache::GrpIterator const &Grp) {
 	if (unlikely(pattern == NULL))
 	if (unlikely(pattern == NULL))
 		return false;
 		return false;
 	else
 	else
 		return regexec(pattern, Grp.Name(), 0, 0, 0) == 0;
 		return regexec(pattern, Grp.Name(), 0, 0, 0) == 0;
 }
 }
-									/*}}}*/
-PackageNameMatchesRegEx::~PackageNameMatchesRegEx() {			/*{{{*/
+PackageNameMatchesRegEx::~PackageNameMatchesRegEx() {
 	if (pattern == NULL)
 	if (pattern == NULL)
 		return;
 		return;
 	regfree(pattern);
 	regfree(pattern);
 	delete pattern;
 	delete pattern;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
-// Fnmatch support					/*{{{*/
-//----------------------------------------------------------------------
-bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+// Name matches Fnmatch							/*{{{*/
+PackageNameMatchesFnmatch::PackageNameMatchesFnmatch(std::string const &Pattern) :
+   Pattern(Pattern) {}
+bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {
    return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0;
    return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0;
 }
 }
-									/*}}}*/
-bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/
+bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {
    return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0;
    return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
-// CompleteArch to <kernel>-<cpu> tuple					/*{{{*/
+// Architecture matches <kernel>-<cpu> specification			/*{{{*/
 //----------------------------------------------------------------------
 //----------------------------------------------------------------------
 /* The complete architecture, consisting of <kernel>-<cpu>. */
 /* The complete architecture, consisting of <kernel>-<cpu>. */
 static std::string CompleteArch(std::string const &arch) {
 static std::string CompleteArch(std::string const &arch) {
@@ -82,12 +82,10 @@ static std::string CompleteArch(std::string const &arch) {
 	else if (arch == "any")			return "*-*";
 	else if (arch == "any")			return "*-*";
 	else					return "linux-" + arch;
 	else					return "linux-" + arch;
 }
 }
-									/*}}}*/
-PackageArchitectureMatchesSpecification::PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern) :/*{{{*/
-					literal(pattern), complete(CompleteArch(pattern)), isPattern(isPattern), d(NULL) {
+PackageArchitectureMatchesSpecification::PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern) :
+					literal(pattern), complete(CompleteArch(pattern)), isPattern(isPattern) {
 }
 }
-									/*}}}*/
-bool PackageArchitectureMatchesSpecification::operator() (char const * const &arch) {/*{{{*/
+bool PackageArchitectureMatchesSpecification::operator() (char const * const &arch) {
 	if (strcmp(literal.c_str(), arch) == 0 ||
 	if (strcmp(literal.c_str(), arch) == 0 ||
 	    strcmp(complete.c_str(), arch) == 0)
 	    strcmp(complete.c_str(), arch) == 0)
 		return true;
 		return true;
@@ -96,16 +94,112 @@ bool PackageArchitectureMatchesSpecification::operator() (char const * const &ar
 		return fnmatch(complete.c_str(), pkgarch.c_str(), 0) == 0;
 		return fnmatch(complete.c_str(), pkgarch.c_str(), 0) == 0;
 	return fnmatch(pkgarch.c_str(), complete.c_str(), 0) == 0;
 	return fnmatch(pkgarch.c_str(), complete.c_str(), 0) == 0;
 }
 }
-									/*}}}*/
-bool PackageArchitectureMatchesSpecification::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+bool PackageArchitectureMatchesSpecification::operator() (pkgCache::PkgIterator const &Pkg) {
 	return (*this)(Pkg.Arch());
 	return (*this)(Pkg.Arch());
+}
+PackageArchitectureMatchesSpecification::~PackageArchitectureMatchesSpecification() {
 }
 }
 									/*}}}*/
 									/*}}}*/
-bool PackageArchitectureMatchesSpecification::operator() (pkgCache::VerIterator const &Ver) {/*{{{*/
-	return (*this)(Ver.ParentPkg());
+// Package is new install						/*{{{*/
+PackageIsNewInstall::PackageIsNewInstall(pkgCacheFile * const Cache) : Cache(Cache) {}
+APT_PURE bool PackageIsNewInstall::operator() (pkgCache::PkgIterator const &Pkg) {
+   return (*Cache)[Pkg].NewInstall();
 }
 }
+PackageIsNewInstall::~PackageIsNewInstall() {}
 									/*}}}*/
 									/*}}}*/
-PackageArchitectureMatchesSpecification::~PackageArchitectureMatchesSpecification() {	/*{{{*/
+// Generica like True, False, NOT, AND, OR				/*{{{*/
+APT_CONST bool TrueMatcher::operator() (pkgCache::PkgIterator const &) { return true; }
+APT_CONST bool TrueMatcher::operator() (pkgCache::GrpIterator const &) { return true; }
+APT_CONST bool TrueMatcher::operator() (pkgCache::VerIterator const &) { return true; }
+
+APT_CONST bool FalseMatcher::operator() (pkgCache::PkgIterator const &) { return false; }
+APT_CONST bool FalseMatcher::operator() (pkgCache::GrpIterator const &) { return false; }
+APT_CONST bool FalseMatcher::operator() (pkgCache::VerIterator const &) { return false; }
+
+NOTMatcher::NOTMatcher(Matcher * const matcher) : matcher(matcher) {}
+bool NOTMatcher::operator() (pkgCache::PkgIterator const &Pkg) { return ! (*matcher)(Pkg); }
+bool NOTMatcher::operator() (pkgCache::GrpIterator const &Grp) { return ! (*matcher)(Grp); }
+bool NOTMatcher::operator() (pkgCache::VerIterator const &Ver) { return ! (*matcher)(Ver); }
+NOTMatcher::~NOTMatcher() { delete matcher; }
+
+ANDMatcher::ANDMatcher() {}
+ANDMatcher::ANDMatcher(Matcher * const matcher1) {
+   AND(matcher1);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2) {
+   AND(matcher1).AND(matcher2);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3) {
+   AND(matcher1).AND(matcher2).AND(matcher3);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4) {
+   AND(matcher1).AND(matcher2).AND(matcher3).AND(matcher4);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5) {
+   AND(matcher1).AND(matcher2).AND(matcher3).AND(matcher4).AND(matcher5);
+}
+ANDMatcher& ANDMatcher::AND(Matcher * const matcher) { matchers.push_back(matcher); return *this; }
+bool ANDMatcher::operator() (pkgCache::PkgIterator const &Pkg) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Pkg) == false)
+	 return false;
+   return true;
+}
+bool ANDMatcher::operator() (pkgCache::GrpIterator const &Grp) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Grp) == false)
+	 return false;
+   return true;
+}
+bool ANDMatcher::operator() (pkgCache::VerIterator const &Ver) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Ver) == false)
+	 return false;
+   return true;
+}
+ANDMatcher::~ANDMatcher() {
+   for (std::vector<Matcher *>::iterator M = matchers.begin(); M != matchers.end(); ++M)
+      delete *M;
+}
+
+ORMatcher::ORMatcher() {}
+ORMatcher::ORMatcher(Matcher * const matcher1) {
+   OR(matcher1);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2) {
+   OR(matcher1).OR(matcher2);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3) {
+   OR(matcher1).OR(matcher2).OR(matcher3);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4) {
+   OR(matcher1).OR(matcher2).OR(matcher3).OR(matcher4);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5) {
+   OR(matcher1).OR(matcher2).OR(matcher3).OR(matcher4).OR(matcher5);
+}
+ORMatcher& ORMatcher::OR(Matcher * const matcher) { matchers.push_back(matcher); return *this; }
+bool ORMatcher::operator() (pkgCache::PkgIterator const &Pkg) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Pkg) == true)
+	 return true;
+   return false;
+}
+bool ORMatcher::operator() (pkgCache::GrpIterator const &Grp) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Grp) == true)
+	 return true;
+   return false;
+}
+bool ORMatcher::operator() (pkgCache::VerIterator const &Ver) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Ver) == true)
+	 return true;
+   return false;
+}
+ORMatcher::~ORMatcher() {
+   for (std::vector<Matcher *>::iterator M = matchers.begin(); M != matchers.end(); ++M)
+      delete *M;
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 

+ 90 - 27
apt-pkg/cachefilter.h

@@ -10,28 +10,90 @@
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/cacheiterators.h>
 
 
 #include <string>
 #include <string>
+#include <vector>
 
 
 #include <regex.h>
 #include <regex.h>
+
+class pkgCacheFile;
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 namespace CacheFilter {
 namespace CacheFilter {
 
 
-class PackageMatcher {
- public:
-   virtual bool operator() (pkgCache::PkgIterator const &/*Pkg*/) { 
-      return false; };
-   virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) { 
-      return false; };
-   virtual bool operator() (pkgCache::VerIterator const &/*Ver*/) {
-      return false; };
-   
-   virtual ~PackageMatcher() {};
+class Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &/*Pkg*/) = 0;
+   virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) = 0;
+   virtual bool operator() (pkgCache::VerIterator const &/*Ver*/) = 0;
+   virtual ~Matcher();
 };
 };
 
 
-// PackageNameMatchesRegEx						/*{{{*/
-class PackageNameMatchesRegEx : public PackageMatcher {
-         /** \brief dpointer placeholder (for later in case we need it) */
-         void *d;
+class PackageMatcher : public Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg) = 0;
+   virtual bool operator() (pkgCache::VerIterator const &Ver) { return (*this)(Ver.ParentPkg()); }
+   virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) { return false; }
+   virtual ~PackageMatcher();
+};
+
+// Generica like True, False, NOT, AND, OR				/*{{{*/
+class TrueMatcher : public Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+};
+
+class FalseMatcher : public Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+};
+
+class NOTMatcher : public Matcher {
+   Matcher * const matcher;
+public:
+   NOTMatcher(Matcher * const matcher);
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+   virtual ~NOTMatcher();
+};
+
+class ANDMatcher : public Matcher {
+   std::vector<Matcher *> matchers;
+public:
+   // 5 ought to be enough for everybody… c++11 variadic templates would be nice
+   ANDMatcher();
+   ANDMatcher(Matcher * const matcher1);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5);
+   ANDMatcher& AND(Matcher * const matcher);
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+   virtual ~ANDMatcher();
+};
+class ORMatcher : public Matcher {
+   std::vector<Matcher *> matchers;
+public:
+   // 5 ought to be enough for everybody… c++11 variadic templates would be nice
+   ORMatcher();
+   ORMatcher(Matcher * const matcher1);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5);
+   ORMatcher& OR(Matcher * const matcher);
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+   virtual ~ORMatcher();
+};
+									/*}}}*/
+class PackageNameMatchesRegEx : public PackageMatcher {			/*{{{*/
 	regex_t* pattern;
 	regex_t* pattern;
 public:
 public:
 	PackageNameMatchesRegEx(std::string const &Pattern);
 	PackageNameMatchesRegEx(std::string const &Pattern);
@@ -40,20 +102,16 @@ public:
 	virtual ~PackageNameMatchesRegEx();
 	virtual ~PackageNameMatchesRegEx();
 };
 };
 									/*}}}*/
 									/*}}}*/
-// PackageNameMatchesFnmatch						/*{{{*/
-   class PackageNameMatchesFnmatch : public PackageMatcher{
-         /** \brief dpointer placeholder (for later in case we need it) */
-         void *d;
-         const std::string Pattern;
+class PackageNameMatchesFnmatch : public PackageMatcher {		/*{{{*/
+	const std::string Pattern;
 public:
 public:
-         PackageNameMatchesFnmatch(std::string const &Pattern) 
-            : Pattern(Pattern) {};
-        virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+	PackageNameMatchesFnmatch(std::string const &Pattern);
+	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
 	virtual bool operator() (pkgCache::GrpIterator const &Grp);
 	virtual bool operator() (pkgCache::GrpIterator const &Grp);
 	virtual ~PackageNameMatchesFnmatch() {};
 	virtual ~PackageNameMatchesFnmatch() {};
 };
 };
 									/*}}}*/
 									/*}}}*/
-// PackageArchitectureMatchesSpecification				/*{{{*/
+class PackageArchitectureMatchesSpecification : public PackageMatcher {	/*{{{*/
 /** \class PackageArchitectureMatchesSpecification
 /** \class PackageArchitectureMatchesSpecification
    \brief matching against architecture specification strings
    \brief matching against architecture specification strings
 
 
@@ -62,12 +120,9 @@ public:
    debian-policy §11.1 "Architecture specification strings".
    debian-policy §11.1 "Architecture specification strings".
 
 
    Examples: i386, mipsel, linux-any, any-amd64, any */
    Examples: i386, mipsel, linux-any, any-amd64, any */
-class PackageArchitectureMatchesSpecification : public PackageMatcher {
 	std::string literal;
 	std::string literal;
 	std::string complete;
 	std::string complete;
 	bool isPattern;
 	bool isPattern;
-	/** \brief dpointer placeholder (for later in case we need it) */
-	void *d;
 public:
 public:
 	/** \brief matching against architecture specification strings
 	/** \brief matching against architecture specification strings
 	 *
 	 *
@@ -79,10 +134,18 @@ public:
 	PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true);
 	PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true);
 	bool operator() (char const * const &arch);
 	bool operator() (char const * const &arch);
 	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
 	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
-	virtual bool operator() (pkgCache::VerIterator const &Ver);
 	virtual ~PackageArchitectureMatchesSpecification();
 	virtual ~PackageArchitectureMatchesSpecification();
 };
 };
 									/*}}}*/
 									/*}}}*/
+class PackageIsNewInstall : public PackageMatcher {			/*{{{*/
+	pkgCacheFile * const Cache;
+public:
+	PackageIsNewInstall(pkgCacheFile * const Cache);
+	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+	virtual ~PackageIsNewInstall();
+};
+									/*}}}*/
+
 }
 }
 }
 }
 #endif
 #endif

+ 13 - 3
apt-pkg/cacheiterators.h

@@ -159,8 +159,12 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> {
 	enum OkState {NeedsNothing,NeedsUnpack,NeedsConfigure};
 	enum OkState {NeedsNothing,NeedsUnpack,NeedsConfigure};
 
 
 	// Accessors
 	// Accessors
-	inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;}
-	inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}
+	inline const char *Name() const { return Group().Name(); }
+	// Versions have sections - and packages can have different versions with different sections
+	// so this interface is broken by design. It used to return the section of the "first parsed
+	// package stanza", but as this can potentially be anything it now returns the section of the
+	// newest version instead (if any). aka: Run as fast as you can to Version.Section().
+	APT_DEPRECATED const char *Section() const;
 	inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge ||
 	inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge ||
 		(S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);}
 		(S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);}
 	inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;}
 	inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;}
@@ -211,6 +215,12 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 	// Accessors
 	// Accessors
 	inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}
 	inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}
 	inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}
 	inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}
+	/** \brief source package name this version comes from
+	   Always contains the name, even if it is the same as the binary name */
+	inline const char *SourcePkgName() const {return Owner->StrP + S->SourcePkgName;}
+	/** \brief source version this version comes from
+	   Always contains the version string, even if it is the same as the binary version */
+	inline const char *SourceVerStr() const {return Owner->StrP + S->SourceVerStr;}
 	inline const char *Arch() const {
 	inline const char *Arch() const {
 		if ((S->MultiArch & pkgCache::Version::All) == pkgCache::Version::All)
 		if ((S->MultiArch & pkgCache::Version::All) == pkgCache::Version::All)
 			return "all";
 			return "all";
@@ -332,7 +342,7 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 	inline void operator ++() {operator ++(0);}
 	inline void operator ++() {operator ++(0);}
 
 
 	// Accessors
 	// Accessors
-	inline const char *Name() const {return Owner->StrP + Owner->PkgP[S->ParentPkg].Name;}
+	inline const char *Name() const {return ParentPkg().Name();}
 	inline const char *ProvideVersion() const {return S->ProvideVersion == 0?0:Owner->StrP + S->ProvideVersion;}
 	inline const char *ProvideVersion() const {return S->ProvideVersion == 0?0:Owner->StrP + S->ProvideVersion;}
 	inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}
 	inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}
 	inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);}
 	inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);}

+ 259 - 110
apt-pkg/cacheset.cc

@@ -24,6 +24,7 @@
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/fileutl.h>
 
 
 #include <stddef.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -36,8 +37,23 @@
 #include <apti18n.h>
 #include <apti18n.h>
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
-// FromTask - Return all packages in the cache from a specific task	/*{{{*/
-bool PackageContainerInterface::FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+
+// PackageFrom - selecting the appropriate method for package selection	/*{{{*/
+bool CacheSetHelper::PackageFrom(enum PkgSelector const select, PackageContainerInterface * const pci,
+      pkgCacheFile &Cache, std::string const &pattern) {
+	switch (select) {
+	case UNKNOWN: return false;
+	case REGEX: return PackageFromRegEx(pci, Cache, pattern);
+	case TASK: return PackageFromTask(pci, Cache, pattern);
+	case FNMATCH: return PackageFromFnmatch(pci, Cache, pattern);
+	case PACKAGENAME: return PackageFromPackageName(pci, Cache, pattern);
+	case STRING: return PackageFromString(pci, Cache, pattern);
+	}
+	return false;
+}
+									/*}}}*/
+// PackageFromTask - Return all packages in the cache from a specific task /*{{{*/
+bool CacheSetHelper::PackageFromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern) {
 	size_t const archfound = pattern.find_last_of(':');
 	size_t const archfound = pattern.find_last_of(':');
 	std::string arch = "native";
 	std::string arch = "native";
 	if (archfound != std::string::npos) {
 	if (archfound != std::string::npos) {
@@ -54,7 +70,7 @@ bool PackageContainerInterface::FromTask(PackageContainerInterface * const pci,
 
 
 	bool const wasEmpty = pci->empty();
 	bool const wasEmpty = pci->empty();
 	if (wasEmpty == true)
 	if (wasEmpty == true)
-		pci->setConstructor(TASK);
+		pci->setConstructor(CacheSetHelper::TASK);
 
 
 	// get the records
 	// get the records
 	pkgRecords Recs(Cache);
 	pkgRecords Recs(Cache);
@@ -90,32 +106,32 @@ bool PackageContainerInterface::FromTask(PackageContainerInterface * const pci,
 			continue;
 			continue;
 
 
 		pci->insert(Pkg);
 		pci->insert(Pkg);
-		helper.showTaskSelection(Pkg, pattern);
+		showPackageSelection(Pkg, CacheSetHelper::TASK, pattern);
 		found = true;
 		found = true;
 	}
 	}
 	regfree(&Pattern);
 	regfree(&Pattern);
 
 
 	if (found == false) {
 	if (found == false) {
-		helper.canNotFindTask(pci, Cache, pattern);
-		pci->setConstructor(UNKNOWN);
+		canNotFindPackage(CacheSetHelper::TASK, pci, Cache, pattern);
+		pci->setConstructor(CacheSetHelper::UNKNOWN);
 		return false;
 		return false;
 	}
 	}
 
 
-	if (wasEmpty == false && pci->getConstructor() != UNKNOWN)
-		pci->setConstructor(UNKNOWN);
+	if (wasEmpty == false && pci->getConstructor() != CacheSetHelper::UNKNOWN)
+		pci->setConstructor(CacheSetHelper::UNKNOWN);
 
 
 	return true;
 	return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// FromRegEx - Return all packages in the cache matching a pattern	/*{{{*/
-bool PackageContainerInterface::FromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+// PackageFromRegEx - Return all packages in the cache matching a pattern /*{{{*/
+bool CacheSetHelper::PackageFromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern) {
 	static const char * const isregex = ".?+*|[^$";
 	static const char * const isregex = ".?+*|[^$";
 	if (pattern.find_first_of(isregex) == std::string::npos)
 	if (pattern.find_first_of(isregex) == std::string::npos)
 		return false;
 		return false;
 
 
 	bool const wasEmpty = pci->empty();
 	bool const wasEmpty = pci->empty();
 	if (wasEmpty == true)
 	if (wasEmpty == true)
-		pci->setConstructor(REGEX);
+		pci->setConstructor(CacheSetHelper::REGEX);
 
 
 	size_t archfound = pattern.find_last_of(':');
 	size_t archfound = pattern.find_last_of(':');
 	std::string arch = "native";
 	std::string arch = "native";
@@ -149,28 +165,25 @@ bool PackageContainerInterface::FromRegEx(PackageContainerInterface * const pci,
 		}
 		}
 
 
 		pci->insert(Pkg);
 		pci->insert(Pkg);
-		helper.showRegExSelection(Pkg, pattern);
+		showPackageSelection(Pkg, CacheSetHelper::REGEX, pattern);
 		found = true;
 		found = true;
 	}
 	}
 
 
 	if (found == false) {
 	if (found == false) {
-		helper.canNotFindRegEx(pci, Cache, pattern);
-		pci->setConstructor(UNKNOWN);
+		canNotFindPackage(CacheSetHelper::REGEX, pci, Cache, pattern);
+		pci->setConstructor(CacheSetHelper::UNKNOWN);
 		return false;
 		return false;
 	}
 	}
 
 
-	if (wasEmpty == false && pci->getConstructor() != UNKNOWN)
-		pci->setConstructor(UNKNOWN);
+	if (wasEmpty == false && pci->getConstructor() != CacheSetHelper::UNKNOWN)
+		pci->setConstructor(CacheSetHelper::UNKNOWN);
 
 
 	return true;
 	return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// FromFnmatch - Returns the package defined  by this fnmatch		/*{{{*/
-bool 
-PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci, 
-                                       pkgCacheFile &Cache,
-                                       std::string pattern,
-                                       CacheSetHelper &helper)
+// PackageFromFnmatch - Returns the package defined  by this fnmatch	/*{{{*/
+bool CacheSetHelper::PackageFromFnmatch(PackageContainerInterface * const pci,
+                                       pkgCacheFile &Cache, std::string pattern)
 {
 {
 	static const char * const isfnmatch = ".?*[]!";
 	static const char * const isfnmatch = ".?*[]!";
 	if (pattern.find_first_of(isfnmatch) == std::string::npos)
 	if (pattern.find_first_of(isfnmatch) == std::string::npos)
@@ -178,7 +191,7 @@ PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci,
 
 
 	bool const wasEmpty = pci->empty();
 	bool const wasEmpty = pci->empty();
 	if (wasEmpty == true)
 	if (wasEmpty == true)
-		pci->setConstructor(FNMATCH);
+		pci->setConstructor(CacheSetHelper::FNMATCH);
 
 
 	size_t archfound = pattern.find_last_of(':');
 	size_t archfound = pattern.find_last_of(':');
 	std::string arch = "native";
 	std::string arch = "native";
@@ -212,33 +225,25 @@ PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci,
 		}
 		}
 
 
 		pci->insert(Pkg);
 		pci->insert(Pkg);
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-		helper.showFnmatchSelection(Pkg, pattern);
-#else
-		helper.showRegExSelection(Pkg, pattern);
-#endif
+		showPackageSelection(Pkg, CacheSetHelper::FNMATCH, pattern);
 		found = true;
 		found = true;
 	}
 	}
 
 
 	if (found == false) {
 	if (found == false) {
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-		helper.canNotFindFnmatch(pci, Cache, pattern);
-#else
-                helper.canNotFindRegEx(pci, Cache, pattern);
-#endif
-		pci->setConstructor(UNKNOWN);
+		canNotFindPackage(CacheSetHelper::FNMATCH, pci, Cache, pattern);
+		pci->setConstructor(CacheSetHelper::UNKNOWN);
 		return false;
 		return false;
 	}
 	}
 
 
-	if (wasEmpty == false && pci->getConstructor() != UNKNOWN)
-		pci->setConstructor(UNKNOWN);
+	if (wasEmpty == false && pci->getConstructor() != CacheSetHelper::UNKNOWN)
+		pci->setConstructor(CacheSetHelper::UNKNOWN);
 
 
 	return true;
 	return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// FromName - Returns the package defined  by this string		/*{{{*/
-pkgCache::PkgIterator PackageContainerInterface::FromName(pkgCacheFile &Cache,
-			std::string const &str, CacheSetHelper &helper) {
+// PackageFromName - Returns the package defined  by this string	/*{{{*/
+pkgCache::PkgIterator CacheSetHelper::PackageFromName(pkgCacheFile &Cache,
+			std::string const &str) {
 	std::string pkg = str;
 	std::string pkg = str;
 	size_t archfound = pkg.find_last_of(':');
 	size_t archfound = pkg.find_last_of(':');
 	std::string arch;
 	std::string arch;
@@ -259,13 +264,13 @@ pkgCache::PkgIterator PackageContainerInterface::FromName(pkgCacheFile &Cache,
 		Pkg = Cache.GetPkgCache()->FindPkg(pkg, arch);
 		Pkg = Cache.GetPkgCache()->FindPkg(pkg, arch);
 
 
 	if (Pkg.end() == true)
 	if (Pkg.end() == true)
-		return helper.canNotFindPkgName(Cache, str);
+		return canNotFindPkgName(Cache, str);
 	return Pkg;
 	return Pkg;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// FromGroup - Returns the package defined  by this string		/*{{{*/
-bool PackageContainerInterface::FromGroup(PackageContainerInterface * const pci, pkgCacheFile &Cache,
-			std::string pkg, CacheSetHelper &helper) {
+// PackageFromPackageName - Returns the package defined  by this string /*{{{*/
+bool CacheSetHelper::PackageFromPackageName(PackageContainerInterface * const pci, pkgCacheFile &Cache,
+			std::string pkg) {
 	if (unlikely(Cache.GetPkgCache() == 0))
 	if (unlikely(Cache.GetPkgCache() == 0))
 		return false;
 		return false;
 
 
@@ -305,7 +310,7 @@ bool PackageContainerInterface::FromGroup(PackageContainerInterface * const pci,
 		}
 		}
 	}
 	}
 
 
-	pkgCache::PkgIterator Pkg = helper.canNotFindPkgName(Cache, pkg);
+	pkgCache::PkgIterator Pkg = canNotFindPkgName(Cache, pkg);
 	if (Pkg.end() == true)
 	if (Pkg.end() == true)
 	   return false;
 	   return false;
 
 
@@ -313,20 +318,18 @@ bool PackageContainerInterface::FromGroup(PackageContainerInterface * const pci,
 	return true;
 	return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// FromString - Return all packages matching a specific string		/*{{{*/
-bool PackageContainerInterface::FromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str, CacheSetHelper &helper) {
+// PackageFromString - Return all packages matching a specific string	/*{{{*/
+bool CacheSetHelper::PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str) {
 	bool found = true;
 	bool found = true;
 	_error->PushToStack();
 	_error->PushToStack();
 
 
-	if (FromGroup(pci, Cache, str, helper) == false &&
-		 FromTask(pci, Cache, str, helper) == false &&
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-                 // FIXME: hm, hm, regexp/fnmatch incompatible?
-		 FromFnmatch(pci, Cache, str, helper) == false &&
-#endif
-		 FromRegEx(pci, Cache, str, helper) == false)
+	if (PackageFrom(CacheSetHelper::PACKAGENAME, pci, Cache, str) == false &&
+		 PackageFrom(CacheSetHelper::TASK, pci, Cache, str) == false &&
+		 // FIXME: hm, hm, regexp/fnmatch incompatible?
+		 PackageFrom(CacheSetHelper::FNMATCH, pci, Cache, str) == false &&
+		 PackageFrom(CacheSetHelper::REGEX, pci, Cache, str) == false)
 	{
 	{
-		helper.canNotFindPackage(pci, Cache, str);
+		canNotFindPackage(CacheSetHelper::PACKAGENAME, pci, Cache, str);
 		found = false;
 		found = false;
 	}
 	}
 
 
@@ -337,51 +340,50 @@ bool PackageContainerInterface::FromString(PackageContainerInterface * const pci
 	return found;
 	return found;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// FromCommandLine - Return all packages specified on commandline	/*{{{*/
-bool PackageContainerInterface::FromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper) {
+// PackageFromCommandLine - Return all packages specified on commandline /*{{{*/
+bool CacheSetHelper::PackageFromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline) {
 	bool found = false;
 	bool found = false;
 	for (const char **I = cmdline; *I != 0; ++I)
 	for (const char **I = cmdline; *I != 0; ++I)
-		found |= PackageContainerInterface::FromString(pci, Cache, *I, helper);
+		found |= PackageFrom(CacheSetHelper::PACKAGENAME, pci, Cache, *I);
 	return found;
 	return found;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FromModifierCommandLine - helper doing the work for PKG:GroupedFromCommandLine	/*{{{*/
 // FromModifierCommandLine - helper doing the work for PKG:GroupedFromCommandLine	/*{{{*/
-bool PackageContainerInterface::FromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci,
+bool CacheSetHelper::PackageFromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci,
 							pkgCacheFile &Cache, const char * cmdline,
 							pkgCacheFile &Cache, const char * cmdline,
-							std::list<Modifier> const &mods, CacheSetHelper &helper) {
+							std::list<PkgModifier> const &mods) {
 	std::string str = cmdline;
 	std::string str = cmdline;
 	unsigned short fallback = modID;
 	unsigned short fallback = modID;
 	bool modifierPresent = false;
 	bool modifierPresent = false;
-	for (std::list<Modifier>::const_iterator mod = mods.begin();
+	for (std::list<PkgModifier>::const_iterator mod = mods.begin();
 	     mod != mods.end(); ++mod) {
 	     mod != mods.end(); ++mod) {
 		size_t const alength = strlen(mod->Alias);
 		size_t const alength = strlen(mod->Alias);
 		switch(mod->Pos) {
 		switch(mod->Pos) {
-		case Modifier::POSTFIX:
+		case PkgModifier::POSTFIX:
 			if (str.compare(str.length() - alength, alength,
 			if (str.compare(str.length() - alength, alength,
 					mod->Alias, 0, alength) != 0)
 					mod->Alias, 0, alength) != 0)
 				continue;
 				continue;
 			str.erase(str.length() - alength);
 			str.erase(str.length() - alength);
 			modID = mod->ID;
 			modID = mod->ID;
 			break;
 			break;
-		case Modifier::PREFIX:
+		case PkgModifier::PREFIX:
 			continue;
 			continue;
-		case Modifier::NONE:
+		case PkgModifier::NONE:
 			continue;
 			continue;
 		}
 		}
 		modifierPresent = true;
 		modifierPresent = true;
 		break;
 		break;
 	}
 	}
 	if (modifierPresent == true) {
 	if (modifierPresent == true) {
-		bool const errors = helper.showErrors(false);
-		pkgCache::PkgIterator Pkg = FromName(Cache, cmdline, helper);
-		helper.showErrors(errors);
-		if (Pkg.end() == false) {
-			pci->insert(Pkg);
+		bool const errors = showErrors(false);
+		bool const found = PackageFrom(PACKAGENAME, pci, Cache, cmdline);
+		showErrors(errors);
+		if (found == true) {
 			modID = fallback;
 			modID = fallback;
 			return true;
 			return true;
 		}
 		}
 	}
 	}
-	return FromString(pci, Cache, str, helper);
+	return PackageFrom(CacheSetHelper::PACKAGENAME, pci, Cache, str);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FromModifierCommandLine - helper doing the work for VER:GroupedFromCommandLine	/*{{{*/
 // FromModifierCommandLine - helper doing the work for VER:GroupedFromCommandLine	/*{{{*/
@@ -390,7 +392,7 @@ bool VersionContainerInterface::FromModifierCommandLine(unsigned short &modID,
 							pkgCacheFile &Cache, const char * cmdline,
 							pkgCacheFile &Cache, const char * cmdline,
 							std::list<Modifier> const &mods,
 							std::list<Modifier> const &mods,
 							CacheSetHelper &helper) {
 							CacheSetHelper &helper) {
-	Version select = NEWEST;
+	CacheSetHelper::VerSelector select = CacheSetHelper::NEWEST;
 	std::string str = cmdline;
 	std::string str = cmdline;
 	if (unlikely(str.empty() == true))
 	if (unlikely(str.empty() == true))
 		return false;
 		return false;
@@ -433,7 +435,8 @@ bool VersionContainerInterface::FromModifierCommandLine(unsigned short &modID,
 // FromCommandLine - Return all versions specified on commandline	/*{{{*/
 // FromCommandLine - Return all versions specified on commandline	/*{{{*/
 bool VersionContainerInterface::FromCommandLine(VersionContainerInterface * const vci,
 bool VersionContainerInterface::FromCommandLine(VersionContainerInterface * const vci,
 						pkgCacheFile &Cache, const char **cmdline,
 						pkgCacheFile &Cache, const char **cmdline,
-						Version const &fallback, CacheSetHelper &helper) {
+						CacheSetHelper::VerSelector const fallback,
+						CacheSetHelper &helper) {
 	bool found = false;
 	bool found = false;
 	for (const char **I = cmdline; *I != 0; ++I)
 	for (const char **I = cmdline; *I != 0; ++I)
 		found |= VersionContainerInterface::FromString(vci, Cache, *I, fallback, helper);
 		found |= VersionContainerInterface::FromString(vci, Cache, *I, fallback, helper);
@@ -443,8 +446,17 @@ bool VersionContainerInterface::FromCommandLine(VersionContainerInterface * cons
 // FromString - Returns all versions spedcified by a string		/*{{{*/
 // FromString - Returns all versions spedcified by a string		/*{{{*/
 bool VersionContainerInterface::FromString(VersionContainerInterface * const vci,
 bool VersionContainerInterface::FromString(VersionContainerInterface * const vci,
 					   pkgCacheFile &Cache, std::string pkg,
 					   pkgCacheFile &Cache, std::string pkg,
-					   Version const &fallback, CacheSetHelper &helper,
+					   CacheSetHelper::VerSelector const fallback,
+					   CacheSetHelper &helper,
 					   bool const onlyFromName) {
 					   bool const onlyFromName) {
+	PackageSet pkgset;
+	if(FileExists(pkg)) {
+		helper.PackageFrom(CacheSetHelper::STRING, &pkgset, Cache, pkg);
+		if(pkgset.empty() == true)
+			return false;
+		return VersionContainerInterface::FromPackage(vci, Cache, pkgset.begin(), fallback, helper);
+	}
+
 	std::string ver;
 	std::string ver;
 	bool verIsRel = false;
 	bool verIsRel = false;
 	size_t const vertag = pkg.find_last_of("/=");
 	size_t const vertag = pkg.find_last_of("/=");
@@ -453,15 +465,14 @@ bool VersionContainerInterface::FromString(VersionContainerInterface * const vci
 		verIsRel = (pkg[vertag] == '/');
 		verIsRel = (pkg[vertag] == '/');
 		pkg.erase(vertag);
 		pkg.erase(vertag);
 	}
 	}
-	PackageSet pkgset;
 	if (onlyFromName == false)
 	if (onlyFromName == false)
-		PackageContainerInterface::FromString(&pkgset, Cache, pkg, helper);
+		helper.PackageFrom(CacheSetHelper::STRING, &pkgset, Cache, pkg);
 	else {
 	else {
-		pkgset.insert(PackageContainerInterface::FromName(Cache, pkg, helper));
+		helper.PackageFrom(CacheSetHelper::PACKAGENAME, &pkgset, Cache, pkg);
 	}
 	}
 
 
 	bool errors = true;
 	bool errors = true;
-	if (pkgset.getConstructor() != PackageSet::UNKNOWN)
+	if (pkgset.getConstructor() != CacheSetHelper::UNKNOWN)
 		errors = helper.showErrors(false);
 		errors = helper.showErrors(false);
 
 
 	bool found = false;
 	bool found = false;
@@ -480,7 +491,7 @@ bool VersionContainerInterface::FromString(VersionContainerInterface * const vci
 			if (P->VersionList != 0)
 			if (P->VersionList != 0)
 				V = P.VersionList();
 				V = P.VersionList();
 			else
 			else
-				V = helper.canNotFindNewestVer(Cache, P);
+				V = helper.canNotGetVersion(CacheSetHelper::NEWEST, Cache, P);
 		} else {
 		} else {
 			pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
 			pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
 					pkgVersionMatch::Version));
 					pkgVersionMatch::Version));
@@ -497,11 +508,14 @@ bool VersionContainerInterface::FromString(VersionContainerInterface * const vci
 		}
 		}
 		if (V.end() == true)
 		if (V.end() == true)
 			continue;
 			continue;
-		helper.showSelectedVersion(P, V, ver, verIsRel);
+		if (verIsRel == true)
+			helper.showVersionSelection(P, V, CacheSetHelper::RELEASE, ver);
+		else
+			helper.showVersionSelection(P, V, CacheSetHelper::VERSIONNUMBER, ver);
 		vci->insert(V);
 		vci->insert(V);
 		found = true;
 		found = true;
 	}
 	}
-	if (pkgset.getConstructor() != PackageSet::UNKNOWN)
+	if (pkgset.getConstructor() != CacheSetHelper::UNKNOWN)
 		helper.showErrors(errors);
 		helper.showErrors(errors);
 	return found;
 	return found;
 }
 }
@@ -510,30 +524,30 @@ bool VersionContainerInterface::FromString(VersionContainerInterface * const vci
 bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vci,
 bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vci,
 					    pkgCacheFile &Cache,
 					    pkgCacheFile &Cache,
 					    pkgCache::PkgIterator const &P,
 					    pkgCache::PkgIterator const &P,
-					    Version const &fallback,
+					    CacheSetHelper::VerSelector const fallback,
 					    CacheSetHelper &helper) {
 					    CacheSetHelper &helper) {
 	pkgCache::VerIterator V;
 	pkgCache::VerIterator V;
 	bool showErrors;
 	bool showErrors;
 	bool found = false;
 	bool found = false;
 	switch(fallback) {
 	switch(fallback) {
-	case ALL:
+	case CacheSetHelper::ALL:
 		if (P->VersionList != 0)
 		if (P->VersionList != 0)
 			for (V = P.VersionList(); V.end() != true; ++V)
 			for (V = P.VersionList(); V.end() != true; ++V)
 				found |= vci->insert(V);
 				found |= vci->insert(V);
 		else
 		else
-			helper.canNotFindAllVer(vci, Cache, P);
+			helper.canNotFindVersion(CacheSetHelper::ALL, vci, Cache, P);
 		break;
 		break;
-	case CANDANDINST:
+	case CacheSetHelper::CANDANDINST:
 		found |= vci->insert(getInstalledVer(Cache, P, helper));
 		found |= vci->insert(getInstalledVer(Cache, P, helper));
 		found |= vci->insert(getCandidateVer(Cache, P, helper));
 		found |= vci->insert(getCandidateVer(Cache, P, helper));
 		break;
 		break;
-	case CANDIDATE:
+	case CacheSetHelper::CANDIDATE:
 		found |= vci->insert(getCandidateVer(Cache, P, helper));
 		found |= vci->insert(getCandidateVer(Cache, P, helper));
 		break;
 		break;
-	case INSTALLED:
+	case CacheSetHelper::INSTALLED:
 		found |= vci->insert(getInstalledVer(Cache, P, helper));
 		found |= vci->insert(getInstalledVer(Cache, P, helper));
 		break;
 		break;
-	case CANDINST:
+	case CacheSetHelper::CANDINST:
 		showErrors = helper.showErrors(false);
 		showErrors = helper.showErrors(false);
 		V = getCandidateVer(Cache, P, helper);
 		V = getCandidateVer(Cache, P, helper);
 		if (V.end() == true)
 		if (V.end() == true)
@@ -542,9 +556,9 @@ bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vc
 		if (V.end() == false)
 		if (V.end() == false)
 			found |= vci->insert(V);
 			found |= vci->insert(V);
 		else
 		else
-			helper.canNotFindInstCandVer(vci, Cache, P);
+			helper.canNotFindVersion(CacheSetHelper::CANDINST, vci, Cache, P);
 		break;
 		break;
-	case INSTCAND:
+	case CacheSetHelper::INSTCAND:
 		showErrors = helper.showErrors(false);
 		showErrors = helper.showErrors(false);
 		V = getInstalledVer(Cache, P, helper);
 		V = getInstalledVer(Cache, P, helper);
 		if (V.end() == true)
 		if (V.end() == true)
@@ -553,14 +567,18 @@ bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vc
 		if (V.end() == false)
 		if (V.end() == false)
 			found |= vci->insert(V);
 			found |= vci->insert(V);
 		else
 		else
-			helper.canNotFindInstCandVer(vci, Cache, P);
+			helper.canNotFindVersion(CacheSetHelper::INSTCAND, vci, Cache, P);
 		break;
 		break;
-	case NEWEST:
+	case CacheSetHelper::NEWEST:
 		if (P->VersionList != 0)
 		if (P->VersionList != 0)
 			found |= vci->insert(P.VersionList());
 			found |= vci->insert(P.VersionList());
 		else
 		else
-			helper.canNotFindNewestVer(Cache, P);
+			helper.canNotFindVersion(CacheSetHelper::NEWEST, vci, Cache, P);
 		break;
 		break;
+	case CacheSetHelper::RELEASE:
+	case CacheSetHelper::VERSIONNUMBER:
+		// both make no sense here, so always false
+		return false;
 	}
 	}
 	return found;
 	return found;
 }
 }
@@ -577,7 +595,7 @@ pkgCache::VerIterator VersionContainerInterface::getCandidateVer(pkgCacheFile &C
 		Cand = Cache[Pkg].CandidateVerIter(Cache);
 		Cand = Cache[Pkg].CandidateVerIter(Cache);
 	}
 	}
 	if (Cand.end() == true)
 	if (Cand.end() == true)
-		return helper.canNotFindCandidateVer(Cache, Pkg);
+		return helper.canNotGetVersion(CacheSetHelper::CANDIDATE, Cache, Pkg);
 	return Cand;
 	return Cand;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -585,19 +603,31 @@ pkgCache::VerIterator VersionContainerInterface::getCandidateVer(pkgCacheFile &C
 pkgCache::VerIterator VersionContainerInterface::getInstalledVer(pkgCacheFile &Cache,
 pkgCache::VerIterator VersionContainerInterface::getInstalledVer(pkgCacheFile &Cache,
 		pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
 		pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
 	if (Pkg->CurrentVer == 0)
 	if (Pkg->CurrentVer == 0)
-		return helper.canNotFindInstalledVer(Cache, Pkg);
+		return helper.canNotGetVersion(CacheSetHelper::INSTALLED, Cache, Pkg);
 	return Pkg.CurrentVer();
 	return Pkg.CurrentVer();
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
-// canNotFindPkgName - handle the case no package has this name		/*{{{*/
-pkgCache::PkgIterator CacheSetHelper::canNotFindPkgName(pkgCacheFile &Cache,
-			std::string const &str) {
-	if (ShowError == true)
-		_error->Insert(ErrorType, _("Unable to locate package %s"), str.c_str());
-	return pkgCache::PkgIterator(Cache, 0);
+// canNotFindPackage - with the given selector and pattern		/*{{{*/
+void CacheSetHelper::canNotFindPackage(enum PkgSelector const select,
+      PackageContainerInterface * const pci, pkgCacheFile &Cache,
+      std::string const &pattern) {
+	switch (select) {
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	case REGEX: canNotFindRegEx(pci, Cache, pattern); break;
+	case TASK: canNotFindTask(pci, Cache, pattern); break;
+	case FNMATCH: canNotFindFnmatch(pci, Cache, pattern); break;
+	case PACKAGENAME: canNotFindPackage(pci, Cache, pattern); break;
+	case STRING: canNotFindPackage(pci, Cache, pattern); break;
+	case UNKNOWN: break;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+	}
 }
 }
-									/*}}}*/
 // canNotFindTask - handle the case no package is found for a task	/*{{{*/
 // canNotFindTask - handle the case no package is found for a task	/*{{{*/
 void CacheSetHelper::canNotFindTask(PackageContainerInterface * const /*pci*/, pkgCacheFile &/*Cache*/, std::string pattern) {
 void CacheSetHelper::canNotFindTask(PackageContainerInterface * const /*pci*/, pkgCacheFile &/*Cache*/, std::string pattern) {
 	if (ShowError == true)
 	if (ShowError == true)
@@ -609,17 +639,50 @@ void CacheSetHelper::canNotFindRegEx(PackageContainerInterface * const /*pci*/,
 	if (ShowError == true)
 	if (ShowError == true)
 		_error->Insert(ErrorType, _("Couldn't find any package by regex '%s'"), pattern.c_str());
 		_error->Insert(ErrorType, _("Couldn't find any package by regex '%s'"), pattern.c_str());
 }
 }
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+									/*}}}*/
 // canNotFindFnmatch - handle the case no package is found by a fnmatch	/*{{{*/
 // canNotFindFnmatch - handle the case no package is found by a fnmatch	/*{{{*/
    void CacheSetHelper::canNotFindFnmatch(PackageContainerInterface * const /*pci*/, pkgCacheFile &/*Cache*/, std::string pattern) {
    void CacheSetHelper::canNotFindFnmatch(PackageContainerInterface * const /*pci*/, pkgCacheFile &/*Cache*/, std::string pattern) {
 	if (ShowError == true)
 	if (ShowError == true)
 		_error->Insert(ErrorType, _("Couldn't find any package by glob '%s'"), pattern.c_str());
 		_error->Insert(ErrorType, _("Couldn't find any package by glob '%s'"), pattern.c_str());
 }
 }
-#endif									/*}}}*/
+									/*}}}*/
 // canNotFindPackage - handle the case no package is found from a string/*{{{*/
 // canNotFindPackage - handle the case no package is found from a string/*{{{*/
 APT_CONST void CacheSetHelper::canNotFindPackage(PackageContainerInterface * const /*pci*/, pkgCacheFile &/*Cache*/, std::string const &/*str*/) {
 APT_CONST void CacheSetHelper::canNotFindPackage(PackageContainerInterface * const /*pci*/, pkgCacheFile &/*Cache*/, std::string const &/*str*/) {
 }
 }
 									/*}}}*/
 									/*}}}*/
+									/*}}}*/
+// canNotFindPkgName - handle the case no package has this name		/*{{{*/
+pkgCache::PkgIterator CacheSetHelper::canNotFindPkgName(pkgCacheFile &Cache,
+			std::string const &str) {
+	if (ShowError == true)
+		_error->Insert(ErrorType, _("Unable to locate package %s"), str.c_str());
+	return pkgCache::PkgIterator(Cache, 0);
+}
+									/*}}}*/
+// canNotFindVersion - for package by selector				/*{{{*/
+void CacheSetHelper::canNotFindVersion(enum VerSelector const select, VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg)
+{
+	switch (select) {
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	case ALL: canNotFindAllVer(vci, Cache, Pkg); break;
+	case INSTCAND: canNotFindInstCandVer(vci, Cache, Pkg); break;
+	case CANDINST: canNotFindCandInstVer(vci, Cache, Pkg); break;
+	case NEWEST: canNotFindNewestVer(Cache, Pkg); break;
+	case CANDIDATE: canNotFindCandidateVer(Cache, Pkg); break;
+	case INSTALLED: canNotFindInstalledVer(Cache, Pkg); break;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+	case CANDANDINST: canNotGetCandInstVer(Cache, Pkg); break;
+	case RELEASE:
+	case VERSIONNUMBER:
+		// invalid in this branch
+		break;
+	}
+}
 // canNotFindAllVer							/*{{{*/
 // canNotFindAllVer							/*{{{*/
 void CacheSetHelper::canNotFindAllVer(VersionContainerInterface * const /*vci*/, pkgCacheFile &/*Cache*/,
 void CacheSetHelper::canNotFindAllVer(VersionContainerInterface * const /*vci*/, pkgCacheFile &/*Cache*/,
 		pkgCache::PkgIterator const &Pkg) {
 		pkgCache::PkgIterator const &Pkg) {
@@ -628,19 +691,42 @@ void CacheSetHelper::canNotFindAllVer(VersionContainerInterface * const /*vci*/,
 }
 }
 									/*}}}*/
 									/*}}}*/
 // canNotFindInstCandVer						/*{{{*/
 // canNotFindInstCandVer						/*{{{*/
-void CacheSetHelper::canNotFindInstCandVer(VersionContainerInterface * const /*vci*/, pkgCacheFile &/*Cache*/,
+void CacheSetHelper::canNotFindInstCandVer(VersionContainerInterface * const /*vci*/, pkgCacheFile &Cache,
 		pkgCache::PkgIterator const &Pkg) {
 		pkgCache::PkgIterator const &Pkg) {
-	if (ShowError == true)
-		_error->Insert(ErrorType, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str());
+	canNotGetInstCandVer(Cache, Pkg);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // canNotFindInstCandVer						/*{{{*/
 // canNotFindInstCandVer						/*{{{*/
-void CacheSetHelper::canNotFindCandInstVer(VersionContainerInterface * const /*vci*/, pkgCacheFile &/*Cache*/,
+void CacheSetHelper::canNotFindCandInstVer(VersionContainerInterface * const /*vci*/, pkgCacheFile &Cache,
 		pkgCache::PkgIterator const &Pkg) {
 		pkgCache::PkgIterator const &Pkg) {
-	if (ShowError == true)
-		_error->Insert(ErrorType, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str());
+	canNotGetCandInstVer(Cache, Pkg);
 }
 }
 									/*}}}*/
 									/*}}}*/
+									/*}}}*/
+// canNotGetVersion - for package by selector				/*{{{*/
+pkgCache::VerIterator CacheSetHelper::canNotGetVersion(enum VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+	switch (select) {
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	case NEWEST: return canNotFindNewestVer(Cache, Pkg);
+	case CANDIDATE: return canNotFindCandidateVer(Cache, Pkg);
+	case INSTALLED: return canNotFindInstalledVer(Cache, Pkg);
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+	case CANDINST: return canNotGetCandInstVer(Cache, Pkg);
+	case INSTCAND: return canNotGetInstCandVer(Cache, Pkg);
+	case ALL:
+	case CANDANDINST:
+	case RELEASE:
+	case VERSIONNUMBER:
+		// invalid in this branch
+		return pkgCache::VerIterator(Cache, 0);
+	}
+	return pkgCache::VerIterator(Cache, 0);
+}
 // canNotFindNewestVer							/*{{{*/
 // canNotFindNewestVer							/*{{{*/
 pkgCache::VerIterator CacheSetHelper::canNotFindNewestVer(pkgCacheFile &Cache,
 pkgCache::VerIterator CacheSetHelper::canNotFindNewestVer(pkgCacheFile &Cache,
 		pkgCache::PkgIterator const &Pkg) {
 		pkgCache::PkgIterator const &Pkg) {
@@ -665,6 +751,42 @@ pkgCache::VerIterator CacheSetHelper::canNotFindInstalledVer(pkgCacheFile &Cache
 	return pkgCache::VerIterator(Cache, 0);
 	return pkgCache::VerIterator(Cache, 0);
 }
 }
 									/*}}}*/
 									/*}}}*/
+// canNotFindInstCandVer						/*{{{*/
+pkgCache::VerIterator CacheSetHelper::canNotGetInstCandVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Insert(ErrorType, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str());
+	return pkgCache::VerIterator(Cache, 0);
+}
+									/*}}}*/
+// canNotFindInstCandVer						/*{{{*/
+pkgCache::VerIterator CacheSetHelper::canNotGetCandInstVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Insert(ErrorType, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str());
+	return pkgCache::VerIterator(Cache, 0);
+}
+									/*}}}*/
+									/*}}}*/
+// showPackageSelection - by selector and given pattern			/*{{{*/
+APT_CONST void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum PkgSelector const select,
+				       std::string const &pattern) {
+	switch (select) {
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	case REGEX: showRegExSelection(pkg, pattern); break;
+	case TASK: showTaskSelection(pkg, pattern); break;
+	case FNMATCH: showFnmatchSelection(pkg, pattern); break;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+	case PACKAGENAME: /* no suprises here */ break;
+	case STRING: /* handled by the special cases */ break;
+	case UNKNOWN: break;
+	}
+}
 // showTaskSelection							/*{{{*/
 // showTaskSelection							/*{{{*/
 APT_CONST void CacheSetHelper::showTaskSelection(pkgCache::PkgIterator const &/*pkg*/,
 APT_CONST void CacheSetHelper::showTaskSelection(pkgCache::PkgIterator const &/*pkg*/,
 				       std::string const &/*pattern*/) {
 				       std::string const &/*pattern*/) {
@@ -675,14 +797,41 @@ APT_CONST void CacheSetHelper::showRegExSelection(pkgCache::PkgIterator const &/
 					std::string const &/*pattern*/) {
 					std::string const &/*pattern*/) {
 }
 }
 									/*}}}*/
 									/*}}}*/
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
 // showFnmatchSelection							/*{{{*/
 // showFnmatchSelection							/*{{{*/
 APT_CONST void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const &/*pkg*/,
 APT_CONST void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const &/*pkg*/,
                                          std::string const &/*pattern*/) {
                                          std::string const &/*pattern*/) {
 }
 }
 									/*}}}*/
 									/*}}}*/
+									/*}}}*/
+// showVersionSelection							/*{{{*/
+APT_CONST void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg,
+      pkgCache::VerIterator const &Ver, enum VerSelector const select, std::string const &pattern) {
+	switch (select) {
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 #endif
 #endif
-// showSelectedVersion							/*{{{*/
+	case RELEASE:
+		showSelectedVersion(Pkg, Ver, pattern, true);
+		break;
+	case VERSIONNUMBER:
+		showSelectedVersion(Pkg, Ver, pattern, false);
+		break;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	case NEWEST:
+	case CANDIDATE:
+	case INSTALLED:
+	case CANDINST:
+	case INSTCAND:
+	case ALL:
+	case CANDANDINST:
+		// not really suprises, but in fact: just not implemented
+		break;
+	}
+}
 APT_CONST void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const &/*Pkg*/,
 APT_CONST void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const &/*Pkg*/,
 					 pkgCache::VerIterator const /*Ver*/,
 					 pkgCache::VerIterator const /*Ver*/,
 					 std::string const &/*ver*/,
 					 std::string const &/*ver*/,

+ 475 - 105
apt-pkg/cacheset.h

@@ -13,8 +13,10 @@
 #include <map>
 #include <map>
 #include <set>
 #include <set>
 #include <list>
 #include <list>
+#include <vector>
 #include <string>
 #include <string>
 #include <iterator>
 #include <iterator>
+#include <algorithm>
 
 
 #include <stddef.h>
 #include <stddef.h>
 
 
@@ -51,36 +53,127 @@ public:									/*{{{*/
 			ShowError(ShowError), ErrorType(ErrorType) {}
 			ShowError(ShowError), ErrorType(ErrorType) {}
 	virtual ~CacheSetHelper() {}
 	virtual ~CacheSetHelper() {}
 
 
-	virtual void showTaskSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
-	virtual void showRegExSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-	virtual void showFnmatchSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
-#endif
-	virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
-				 std::string const &ver, bool const verIsRel);
+	enum PkgSelector { UNKNOWN, REGEX, TASK, FNMATCH, PACKAGENAME, STRING };
 
 
-	virtual void canNotFindTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
-	virtual void canNotFindRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-	virtual void canNotFindFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
-#endif
-	virtual void canNotFindPackage(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str);
+	virtual bool PackageFrom(enum PkgSelector const select, PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern);
+
+	virtual bool PackageFromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline);
+
+	struct PkgModifier {
+		enum Position { NONE, PREFIX, POSTFIX };
+		unsigned short ID;
+		const char * const Alias;
+		Position Pos;
+		PkgModifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {}
+	};
+	virtual bool PackageFromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci,
+					    pkgCacheFile &Cache, const char * cmdline,
+					    std::list<PkgModifier> const &mods);
+
+	// use PackageFrom(PACKAGENAME, …) instead
+	APT_DEPRECATED pkgCache::PkgIterator PackageFromName(pkgCacheFile &Cache, std::string const &pattern);
+
+	/** \brief be notified about the package being selected via pattern
+	 *
+	 * Main use is probably to show a message to the user what happened
+	 *
+	 * \param pkg is the package which was selected
+	 * \param select is the selection method which choose the package
+	 * \param pattern is the string used by the selection method to pick the package
+	 */
+	virtual void showPackageSelection(pkgCache::PkgIterator const &pkg, PkgSelector const select, std::string const &pattern);
+	// use the method above instead, react only on the type you need and let the base handle the rest if need be
+	// this allows use to add new selection methods without breaking the ABI constantly with new virtual methods
+	APT_DEPRECATED virtual void showTaskSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
+	APT_DEPRECATED virtual void showRegExSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
+	APT_DEPRECATED virtual void showFnmatchSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
+
+	/** \brief be notified if a package can't be found via pattern
+	 *
+	 * Can be used to show a message as well as to try something else to make it match
+	 *
+	 * \param select is the method tried for selection
+	 * \param pci is the container the package should be inserted in
+	 * \param Cache is the package universe available
+	 * \param pattern is the string not matching anything
+	 */
+	virtual void canNotFindPackage(enum PkgSelector const select, PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern);
+	// same as above for showPackageSelection
+	APT_DEPRECATED virtual void canNotFindTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	APT_DEPRECATED virtual void canNotFindRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	APT_DEPRECATED virtual void canNotFindFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	APT_DEPRECATED virtual void canNotFindPackage(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str);
+
+	/** \brief specifies which version(s) we want to refer to */
+	enum VerSelector {
+		/** by release string */
+		RELEASE,
+		/** by version number string */
+		VERSIONNUMBER,
+		/** All versions */
+		ALL,
+		/** Candidate and installed version */
+		CANDANDINST,
+		/** Candidate version */
+		CANDIDATE,
+		/** Installed version */
+		INSTALLED,
+		/** Candidate or if non installed version */
+		CANDINST,
+		/** Installed or if non candidate version */
+		INSTCAND,
+		/** Newest version */
+		NEWEST
+	};
+
+	/** \brief be notified about the version being selected via pattern
+	 *
+	 * Main use is probably to show a message to the user what happened
+	 * Note that at the moment this method is only called for RELEASE
+	 * and VERSION selections, not for the others.
+	 *
+	 * \param Pkg is the package which was selected for
+	 * \param Ver is the version selected
+	 * \param select is the selection method which choose the version
+	 * \param pattern is the string used by the selection method to pick the version
+	 */
+	virtual void showVersionSelection(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver,
+	      enum VerSelector const select, std::string const &pattern);
+	// renamed to have a similar interface to showPackageSelection
+	APT_DEPRECATED virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+				 std::string const &ver, bool const verIsRel);
 
 
-	virtual void canNotFindAllVer(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);
-	virtual void canNotFindInstCandVer(VersionContainerInterface * const vci, pkgCacheFile &Cache,
+	/** \brief be notified if a version can't be found for a package
+	 *
+	 * Main use is probably to show a message to the user what happened
+	 *
+	 * \param select is the method tried for selection
+	 * \param vci is the container the version should be inserted in
+	 * \param Cache is the package universe available
+	 * \param Pkg is the package we wanted a version from
+	 */
+	virtual void canNotFindVersion(enum VerSelector const select, VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);
+	// same as above for showPackageSelection
+	APT_DEPRECATED virtual void canNotFindAllVer(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);
+	APT_DEPRECATED virtual void canNotFindInstCandVer(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &Pkg);
 				pkgCache::PkgIterator const &Pkg);
-	virtual void canNotFindCandInstVer(VersionContainerInterface * const vci,
+	APT_DEPRECATED virtual void canNotFindCandInstVer(VersionContainerInterface * const vci,
 				pkgCacheFile &Cache,
 				pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &Pkg);
 				pkgCache::PkgIterator const &Pkg);
 
 
-	virtual pkgCache::PkgIterator canNotFindPkgName(pkgCacheFile &Cache, std::string const &str);
-	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache,
+	// the difference between canNotFind and canNotGet is that the later is more low-level
+	// and called from other places: In this case looking into the code is the only real answer…
+	virtual pkgCache::VerIterator canNotGetVersion(enum VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);
+	// same as above for showPackageSelection
+	APT_DEPRECATED virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &Pkg);
 				pkgCache::PkgIterator const &Pkg);
-	virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache,
+	APT_DEPRECATED virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &Pkg);
 				pkgCache::PkgIterator const &Pkg);
-	virtual pkgCache::VerIterator canNotFindInstalledVer(pkgCacheFile &Cache,
+	APT_DEPRECATED virtual pkgCache::VerIterator canNotFindInstalledVer(pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &Pkg);
 				pkgCache::PkgIterator const &Pkg);
 
 
+	virtual pkgCache::PkgIterator canNotFindPkgName(pkgCacheFile &Cache, std::string const &str);
+
 	bool showErrors() const { return ShowError; }
 	bool showErrors() const { return ShowError; }
 	bool showErrors(bool const newValue) { if (ShowError == newValue) return ShowError; else return ((ShowError = newValue) == false); }
 	bool showErrors(bool const newValue) { if (ShowError == newValue) return ShowError; else return ((ShowError = newValue) == false); }
 	GlobalError::MsgType errorType() const { return ErrorType; }
 	GlobalError::MsgType errorType() const { return ErrorType; }
@@ -98,7 +191,19 @@ public:									/*{{{*/
 protected:
 protected:
 	bool ShowError;
 	bool ShowError;
 	GlobalError::MsgType ErrorType;
 	GlobalError::MsgType ErrorType;
+
+	pkgCache::VerIterator canNotGetInstCandVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg);
+	pkgCache::VerIterator canNotGetCandInstVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg);
+
+	bool PackageFromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	bool PackageFromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	bool PackageFromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	bool PackageFromPackageName(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+	bool PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern);
 };									/*}}}*/
 };									/*}}}*/
+
 class PackageContainerInterface {					/*{{{*/
 class PackageContainerInterface {					/*{{{*/
 /** \class PackageContainerInterface
 /** \class PackageContainerInterface
 
 
@@ -118,7 +223,16 @@ public:
 		inline const char *Name() const {return getPkg().Name(); }
 		inline const char *Name() const {return getPkg().Name(); }
 		inline std::string FullName(bool const Pretty) const { return getPkg().FullName(Pretty); }
 		inline std::string FullName(bool const Pretty) const { return getPkg().FullName(Pretty); }
 		inline std::string FullName() const { return getPkg().FullName(); }
 		inline std::string FullName() const { return getPkg().FullName(); }
-		inline const char *Section() const {return getPkg().Section(); }
+		APT_DEPRECATED inline const char *Section() const {
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	   return getPkg().Section();
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+		}
 		inline bool Purge() const {return getPkg().Purge(); }
 		inline bool Purge() const {return getPkg().Purge(); }
 		inline const char *Arch() const {return getPkg().Arch(); }
 		inline const char *Arch() const {return getPkg().Arch(); }
 		inline pkgCache::GrpIterator Group() const { return getPkg().Group(); }
 		inline pkgCache::GrpIterator Group() const { return getPkg().Group(); }
@@ -142,29 +256,56 @@ public:
 	virtual bool empty() const = 0;
 	virtual bool empty() const = 0;
 	virtual void clear() = 0;
 	virtual void clear() = 0;
 
 
-	enum Constructor { UNKNOWN, REGEX, TASK, FNMATCH };
-	virtual void setConstructor(Constructor const &con) = 0;
-	virtual Constructor getConstructor() const = 0;
-
-	static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
-	static bool FromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
-	static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper);
-	static bool FromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
-	static bool FromGroup(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
-	static bool FromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper);
-	static bool FromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper);
+	// FIXME: This is a bloody hack removed soon. Use CacheSetHelper::PkgSelector !
+	enum APT_DEPRECATED Constructor { UNKNOWN = CacheSetHelper::UNKNOWN,
+		REGEX = CacheSetHelper::REGEX,
+		TASK = CacheSetHelper::TASK,
+		FNMATCH = CacheSetHelper::FNMATCH };
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	void setConstructor(Constructor const by) { ConstructedBy = (CacheSetHelper::PkgSelector)by; }
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
-	struct Modifier {
-		enum Position { NONE, PREFIX, POSTFIX };
-		unsigned short ID;
-		const char * const Alias;
-		Position Pos;
-		Modifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {}
-	};
+	void setConstructor(CacheSetHelper::PkgSelector const by) { ConstructedBy = by; }
+	CacheSetHelper::PkgSelector getConstructor() const { return ConstructedBy; }
+	PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {}
+	PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {}
+
+	APT_DEPRECATED static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+	   return helper.PackageFrom(CacheSetHelper::TASK, pci, Cache, pattern); }
+	APT_DEPRECATED static bool FromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+	   return helper.PackageFrom(CacheSetHelper::REGEX, pci, Cache, pattern); }
+	APT_DEPRECATED static bool FromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+	   return helper.PackageFrom(CacheSetHelper::FNMATCH, pci, Cache, pattern); }
+	APT_DEPRECATED static bool FromGroup(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+	   return helper.PackageFrom(CacheSetHelper::PACKAGENAME, pci, Cache, pattern); }
+	APT_DEPRECATED static bool FromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
+	   return helper.PackageFrom(CacheSetHelper::STRING, pci, Cache, pattern); }
+	APT_DEPRECATED static bool FromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper) {
+	   return helper.PackageFromCommandLine(pci, Cache, cmdline); }
+
+	APT_DEPRECATED typedef CacheSetHelper::PkgModifier Modifier;
+
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	APT_DEPRECATED static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
+	   return helper.PackageFromName(Cache, pattern); }
+	APT_DEPRECATED static bool FromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci,
+	      pkgCacheFile &Cache, const char * cmdline,
+	      std::list<Modifier> const &mods, CacheSetHelper &helper) {
+	   return helper.PackageFromModifierCommandLine(modID, pci, Cache, cmdline, mods); }
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
-	static bool FromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci,
-					    pkgCacheFile &Cache, const char * cmdline,
-					    std::list<Modifier> const &mods, CacheSetHelper &helper);
+private:
+	CacheSetHelper::PkgSelector ConstructedBy;
 };
 };
 									/*}}}*/
 									/*}}}*/
 template<class Container> class PackageContainer : public PackageContainerInterface {/*{{{*/
 template<class Container> class PackageContainer : public PackageContainerInterface {/*{{{*/
@@ -228,11 +369,28 @@ public:									/*{{{*/
 	iterator end() { return iterator(_cont.end()); }
 	iterator end() { return iterator(_cont.end()); }
 	const_iterator find(pkgCache::PkgIterator const &P) const { return const_iterator(_cont.find(P)); }
 	const_iterator find(pkgCache::PkgIterator const &P) const { return const_iterator(_cont.find(P)); }
 
 
-	void setConstructor(Constructor const &by) { ConstructedBy = by; }
-	Constructor getConstructor() const { return ConstructedBy; }
+	PackageContainer() : PackageContainerInterface() {}
+	PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	APT_DEPRECATED PackageContainer(Constructor const &by) : PackageContainerInterface((CacheSetHelper::PkgSelector)by) {}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+
+	/** \brief sort all included versions with given comparer
 
 
-	PackageContainer() : ConstructedBy(UNKNOWN) {}
-	PackageContainer(Constructor const &by) : ConstructedBy(by) {}
+	    Some containers are sorted by default, some are not and can't be,
+	    but a few like std::vector can be sorted if need be, so this can be
+	    specialized in later on. The default is that this will fail though.
+	    Specifically, already sorted containers like std::set will return
+	    false as well as there is no easy way to check that the given comparer
+	    would sort in the same way the set is currently sorted
+
+	    \return \b true if the set was sorted, \b false if not. */
+	template<class Compare> bool sort(Compare /*Comp*/) { return false; }
 
 
 	/** \brief returns all packages in the cache who belong to the given task
 	/** \brief returns all packages in the cache who belong to the given task
 
 
@@ -243,8 +401,8 @@ public:									/*{{{*/
 	    \param pattern name of the task
 	    \param pattern name of the task
 	    \param helper responsible for error and message handling */
 	    \param helper responsible for error and message handling */
 	static PackageContainer FromTask(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
 	static PackageContainer FromTask(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
-		PackageContainer cont(TASK);
-		PackageContainerInterface::FromTask(&cont, Cache, pattern, helper);
+		PackageContainer cont(CacheSetHelper::TASK);
+		helper.PackageFrom(CacheSetHelper::TASK, &cont, Cache, pattern);
 		return cont;
 		return cont;
 	}
 	}
 	static PackageContainer FromTask(pkgCacheFile &Cache, std::string const &pattern) {
 	static PackageContainer FromTask(pkgCacheFile &Cache, std::string const &pattern) {
@@ -260,9 +418,9 @@ public:									/*{{{*/
 	    \param Cache the packages are in
 	    \param Cache the packages are in
 	    \param pattern regular expression for package names
 	    \param pattern regular expression for package names
 	    \param helper responsible for error and message handling */
 	    \param helper responsible for error and message handling */
-	static PackageContainer FromRegEx(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
-		PackageContainer cont(REGEX);
-		PackageContainerInterface::FromRegEx(&cont, Cache, pattern, helper);
+	static PackageContainer FromRegEx(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
+		PackageContainer cont(CacheSetHelper::REGEX);
+		helper.PackageFrom(CacheSetHelper::REGEX, &cont, Cache, pattern);
 		return cont;
 		return cont;
 	}
 	}
 
 
@@ -271,9 +429,9 @@ public:									/*{{{*/
 		return FromRegEx(Cache, pattern, helper);
 		return FromRegEx(Cache, pattern, helper);
 	}
 	}
 
 
-	static PackageContainer FromFnmatch(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
-		PackageContainer cont(FNMATCH);
-		PackageContainerInterface::FromFnmatch(&cont, Cache, pattern, helper);
+	static PackageContainer FromFnmatch(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
+		PackageContainer cont(CacheSetHelper::FNMATCH);
+		helper.PackageFrom(CacheSetHelper::FNMATCH, &cont, Cache, pattern);
 		return cont;
 		return cont;
 	}
 	}
 	static PackageContainer FromFnMatch(pkgCacheFile &Cache, std::string const &pattern) {
 	static PackageContainer FromFnMatch(pkgCacheFile &Cache, std::string const &pattern) {
@@ -281,18 +439,25 @@ public:									/*{{{*/
 		return FromFnmatch(Cache, pattern, helper);
 		return FromFnmatch(Cache, pattern, helper);
 	}
 	}
 
 
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
 	/** \brief returns a package specified by a string
 	/** \brief returns a package specified by a string
 
 
 	    \param Cache the package is in
 	    \param Cache the package is in
 	    \param pattern String the package name should be extracted from
 	    \param pattern String the package name should be extracted from
 	    \param helper responsible for error and message handling */
 	    \param helper responsible for error and message handling */
-	static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
-		return PackageContainerInterface::FromName(Cache, pattern, helper);
+	APT_DEPRECATED static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
+		return helper.PackageFromName(Cache, pattern);
 	}
 	}
-	static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern) {
+	APT_DEPRECATED static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern) {
 		CacheSetHelper helper;
 		CacheSetHelper helper;
-		return PackageContainerInterface::FromName(Cache, pattern, helper);
+		return FromName(Cache, pattern, helper);
 	}
 	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
 	/** \brief returns all packages specified by a string
 	/** \brief returns all packages specified by a string
 
 
@@ -301,7 +466,7 @@ public:									/*{{{*/
 	    \param helper responsible for error and message handling */
 	    \param helper responsible for error and message handling */
 	static PackageContainer FromString(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
 	static PackageContainer FromString(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
 		PackageContainer cont;
 		PackageContainer cont;
-		PackageContainerInterface::FromString(&cont, Cache, pattern, helper);
+		helper.PackageFrom(CacheSetHelper::PACKAGENAME, &cont, Cache, pattern);
 		return cont;
 		return cont;
 	}
 	}
 	static PackageContainer FromString(pkgCacheFile &Cache, std::string const &pattern) {
 	static PackageContainer FromString(pkgCacheFile &Cache, std::string const &pattern) {
@@ -318,7 +483,7 @@ public:									/*{{{*/
 	    \param helper responsible for error and message handling */
 	    \param helper responsible for error and message handling */
 	static PackageContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper) {
 	static PackageContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper) {
 		PackageContainer cont;
 		PackageContainer cont;
-		PackageContainerInterface::FromCommandLine(&cont, Cache, cmdline, helper);
+		helper.PackageFromCommandLine(&cont, Cache, cmdline);
 		return cont;
 		return cont;
 	}
 	}
 	static PackageContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
 	static PackageContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
@@ -340,14 +505,14 @@ public:									/*{{{*/
 	static std::map<unsigned short, PackageContainer> GroupedFromCommandLine(
 	static std::map<unsigned short, PackageContainer> GroupedFromCommandLine(
 										 pkgCacheFile &Cache,
 										 pkgCacheFile &Cache,
 										 const char **cmdline,
 										 const char **cmdline,
-										 std::list<Modifier> const &mods,
+										 std::list<CacheSetHelper::PkgModifier> const &mods,
 										 unsigned short const &fallback,
 										 unsigned short const &fallback,
 										 CacheSetHelper &helper) {
 										 CacheSetHelper &helper) {
 		std::map<unsigned short, PackageContainer> pkgsets;
 		std::map<unsigned short, PackageContainer> pkgsets;
 		for (const char **I = cmdline; *I != 0; ++I) {
 		for (const char **I = cmdline; *I != 0; ++I) {
 			unsigned short modID = fallback;
 			unsigned short modID = fallback;
 			PackageContainer pkgset;
 			PackageContainer pkgset;
-			PackageContainerInterface::FromModifierCommandLine(modID, &pkgset, Cache, *I, mods, helper);
+			helper.PackageFromModifierCommandLine(modID, &pkgset, Cache, *I, mods);
 			pkgsets[modID].insert(pkgset);
 			pkgsets[modID].insert(pkgset);
 		}
 		}
 		return pkgsets;
 		return pkgsets;
@@ -355,22 +520,23 @@ public:									/*{{{*/
 	static std::map<unsigned short, PackageContainer> GroupedFromCommandLine(
 	static std::map<unsigned short, PackageContainer> GroupedFromCommandLine(
 										 pkgCacheFile &Cache,
 										 pkgCacheFile &Cache,
 										 const char **cmdline,
 										 const char **cmdline,
-										 std::list<Modifier> const &mods,
+										 std::list<CacheSetHelper::PkgModifier> const &mods,
 										 unsigned short const &fallback) {
 										 unsigned short const &fallback) {
 		CacheSetHelper helper;
 		CacheSetHelper helper;
 		return GroupedFromCommandLine(Cache, cmdline,
 		return GroupedFromCommandLine(Cache, cmdline,
 				mods, fallback, helper);
 				mods, fallback, helper);
 	}
 	}
 									/*}}}*/
 									/*}}}*/
-private:								/*{{{*/
-	Constructor ConstructedBy;
-									/*}}}*/
 };									/*}}}*/
 };									/*}}}*/
-
+// specialisations for push_back containers: std::list & std::vector	/*{{{*/
 template<> template<class Cont> void PackageContainer<std::list<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) {
 template<> template<class Cont> void PackageContainer<std::list<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) {
 	for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p)
 	for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p)
 		_cont.push_back(*p);
 		_cont.push_back(*p);
 }
 }
+template<> template<class Cont> void PackageContainer<std::vector<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) {
+	for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p)
+		_cont.push_back(*p);
+}
 // these two are 'inline' as otherwise the linker has problems with seeing these untemplated
 // these two are 'inline' as otherwise the linker has problems with seeing these untemplated
 // specializations again and again - but we need to see them, so that library users can use them
 // specializations again and again - but we need to see them, so that library users can use them
 template<> inline bool PackageContainer<std::list<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) {
 template<> inline bool PackageContainer<std::list<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) {
@@ -379,12 +545,65 @@ template<> inline bool PackageContainer<std::list<pkgCache::PkgIterator> >::inse
 	_cont.push_back(P);
 	_cont.push_back(P);
 	return true;
 	return true;
 }
 }
+template<> inline bool PackageContainer<std::vector<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) {
+	if (P.end() == true)
+		return false;
+	_cont.push_back(P);
+	return true;
+}
 template<> inline void PackageContainer<std::list<pkgCache::PkgIterator> >::insert(const_iterator begin, const_iterator end) {
 template<> inline void PackageContainer<std::list<pkgCache::PkgIterator> >::insert(const_iterator begin, const_iterator end) {
 	for (const_iterator p = begin; p != end; ++p)
 	for (const_iterator p = begin; p != end; ++p)
 		_cont.push_back(*p);
 		_cont.push_back(*p);
 }
 }
+template<> inline void PackageContainer<std::vector<pkgCache::PkgIterator> >::insert(const_iterator begin, const_iterator end) {
+	for (const_iterator p = begin; p != end; ++p)
+		_cont.push_back(*p);
+}
+									/*}}}*/
+
+template<> template<class Compare> inline bool PackageContainer<std::vector<pkgCache::PkgIterator> >::sort(Compare Comp) {
+	std::sort(_cont.begin(), _cont.end(), Comp);
+	return true;
+}
+
+// class PackageUniverse - pkgCache as PackageContainerInterface	/*{{{*/
+/** \class PackageUniverse
+
+    Wraps around our usual pkgCache, so that it can be stuffed into methods
+    expecting a PackageContainer.
+
+    The wrapping is read-only in practice modeled by making erase and co
+    private methods. */
+class APT_HIDDEN PackageUniverse : public PackageContainerInterface {
+	pkgCache * const _cont;
+public:
+	typedef pkgCache::PkgIterator iterator;
+	typedef pkgCache::PkgIterator const_iterator;
+
+	APT_PUBLIC bool empty() const { return false; }
+	APT_PUBLIC size_t size() const { return _cont->Head().PackageCount; }
+
+	APT_PUBLIC const_iterator begin() const { return _cont->PkgBegin(); }
+	APT_PUBLIC const_iterator end() const { return  _cont->PkgEnd(); }
+	APT_PUBLIC iterator begin() { return _cont->PkgBegin(); }
+	APT_PUBLIC iterator end() { return _cont->PkgEnd(); }
+
+	APT_PUBLIC PackageUniverse(pkgCache * const Owner) : _cont(Owner) { }
+
+private:
+	bool insert(pkgCache::PkgIterator const &) { return true; }
+	template<class Cont> void insert(PackageContainer<Cont> const &) { }
+	void insert(const_iterator, const_iterator) { }
+
+	void clear() { }
+	iterator& erase(iterator &iter) { return iter; }
+	size_t erase(const pkgCache::PkgIterator) { return 0; }
+	void erase(iterator, iterator) { }
+};
+									/*}}}*/
 typedef PackageContainer<std::set<pkgCache::PkgIterator> > PackageSet;
 typedef PackageContainer<std::set<pkgCache::PkgIterator> > PackageSet;
 typedef PackageContainer<std::list<pkgCache::PkgIterator> > PackageList;
 typedef PackageContainer<std::list<pkgCache::PkgIterator> > PackageList;
+typedef PackageContainer<std::vector<pkgCache::PkgIterator> > PackageVector;
 
 
 class VersionContainerInterface {					/*{{{*/
 class VersionContainerInterface {					/*{{{*/
 /** \class APT::VersionContainerInterface
 /** \class APT::VersionContainerInterface
@@ -426,45 +645,83 @@ public:
 	virtual void clear() = 0;
 	virtual void clear() = 0;
 
 
 	/** \brief specifies which version(s) will be returned if non is given */
 	/** \brief specifies which version(s) will be returned if non is given */
-	enum Version {
-		/** All versions */
-		ALL,
-		/** Candidate and installed version */
-		CANDANDINST,
-		/** Candidate version */
-		CANDIDATE,
-		/** Installed version */
-		INSTALLED,
-		/** Candidate or if non installed version */
-		CANDINST,
-		/** Installed or if non candidate version */
-		INSTCAND,
-		/** Newest version */
-		NEWEST
+	enum APT_DEPRECATED Version {
+		ALL = CacheSetHelper::ALL,
+		CANDANDINST = CacheSetHelper::CANDANDINST,
+		CANDIDATE = CacheSetHelper::CANDIDATE,
+		INSTALLED = CacheSetHelper::INSTALLED,
+		CANDINST = CacheSetHelper::CANDINST,
+		INSTCAND = CacheSetHelper::INSTCAND,
+		NEWEST = CacheSetHelper::NEWEST
 	};
 	};
 
 
 	struct Modifier {
 	struct Modifier {
-		enum Position { NONE, PREFIX, POSTFIX };
-		unsigned short ID;
+		unsigned short const ID;
 		const char * const Alias;
 		const char * const Alias;
-		Position Pos;
-		Version SelectVersion;
+		enum Position { NONE, PREFIX, POSTFIX } const Pos;
+		enum CacheSetHelper::VerSelector const SelectVersion;
 		Modifier (unsigned short const &id, const char * const alias, Position const &pos,
 		Modifier (unsigned short const &id, const char * const alias, Position const &pos,
-			  Version const &select) : ID(id), Alias(alias), Pos(pos),
+			  enum CacheSetHelper::VerSelector const select) : ID(id), Alias(alias), Pos(pos),
 			 SelectVersion(select) {}
 			 SelectVersion(select) {}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+		APT_DEPRECATED Modifier(unsigned short const &id, const char * const alias, Position const &pos,
+			  Version const &select) : ID(id), Alias(alias), Pos(pos),
+			 SelectVersion((CacheSetHelper::VerSelector)select) {}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 	};
 	};
 
 
 	static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 	static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache,
-				    const char **cmdline, Version const &fallback,
+				    const char **cmdline, CacheSetHelper::VerSelector const fallback,
 				    CacheSetHelper &helper);
 				    CacheSetHelper &helper);
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	APT_DEPRECATED static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache,
+				    const char **cmdline, Version const &fallback,
+				    CacheSetHelper &helper) {
+	   return FromCommandLine(vci, Cache, cmdline, (CacheSetHelper::VerSelector)fallback, helper);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
 	static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 	static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache,
-			       std::string pkg, Version const &fallback, CacheSetHelper &helper,
+			       std::string pkg, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper,
 			       bool const onlyFromName = false);
 			       bool const onlyFromName = false);
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	APT_DEPRECATED static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache,
+			       std::string pkg, Version const &fallback, CacheSetHelper &helper,
+			       bool const onlyFromName = false) {
+	   return FromString(vci, Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper, onlyFromName);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
 	static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 	static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache,
-				pkgCache::PkgIterator const &P, Version const &fallback,
+				pkgCache::PkgIterator const &P, CacheSetHelper::VerSelector const fallback,
 				CacheSetHelper &helper);
 				CacheSetHelper &helper);
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	APT_DEPRECATED static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache,
+				pkgCache::PkgIterator const &P, Version const &fallback,
+				CacheSetHelper &helper) {
+	   return FromPackage(vci, Cache, P, (CacheSetHelper::VerSelector)fallback, helper);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
 	static bool FromModifierCommandLine(unsigned short &modID,
 	static bool FromModifierCommandLine(unsigned short &modID,
 					    VersionContainerInterface * const vci,
 					    VersionContainerInterface * const vci,
@@ -476,8 +733,22 @@ public:
 	static bool FromDependency(VersionContainerInterface * const vci,
 	static bool FromDependency(VersionContainerInterface * const vci,
 				   pkgCacheFile &Cache,
 				   pkgCacheFile &Cache,
 				   pkgCache::DepIterator const &D,
 				   pkgCache::DepIterator const &D,
-				   Version const &selector,
+				   CacheSetHelper::VerSelector const selector,
 				   CacheSetHelper &helper);
 				   CacheSetHelper &helper);
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	APT_DEPRECATED static bool FromDependency(VersionContainerInterface * const vci,
+				   pkgCacheFile &Cache,
+				   pkgCache::DepIterator const &D,
+				   Version const &selector,
+				   CacheSetHelper &helper) {
+	   return FromDependency(vci, Cache, D, (CacheSetHelper::VerSelector)selector, helper);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
 protected:								/*{{{*/
 protected:								/*{{{*/
 
 
@@ -559,6 +830,18 @@ public:									/*{{{*/
 	iterator end() { return iterator(_cont.end()); }
 	iterator end() { return iterator(_cont.end()); }
 	const_iterator find(pkgCache::VerIterator const &V) const { return const_iterator(_cont.find(V)); }
 	const_iterator find(pkgCache::VerIterator const &V) const { return const_iterator(_cont.find(V)); }
 
 
+	/** \brief sort all included versions with given comparer
+
+	    Some containers are sorted by default, some are not and can't be,
+	    but a few like std::vector can be sorted if need be, so this can be
+	    specialized in later on. The default is that this will fail though.
+	    Specifically, already sorted containers like std::set will return
+	    false as well as there is no easy way to check that the given comparer
+	    would sort in the same way the set is currently sorted
+
+	    \return \b true if the set was sorted, \b false if not. */
+	template<class Compare> bool sort(Compare /*Comp*/) { return false; }
+
 	/** \brief returns all versions specified on the commandline
 	/** \brief returns all versions specified on the commandline
 
 
 	    Get all versions from the commandline, uses given default version if
 	    Get all versions from the commandline, uses given default version if
@@ -568,35 +851,64 @@ public:									/*{{{*/
 	    \param fallback version specification
 	    \param fallback version specification
 	    \param helper responsible for error and message handling */
 	    \param helper responsible for error and message handling */
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
-			Version const &fallback, CacheSetHelper &helper) {
+			CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper) {
 		VersionContainer vercon;
 		VersionContainer vercon;
 		VersionContainerInterface::FromCommandLine(&vercon, Cache, cmdline, fallback, helper);
 		VersionContainerInterface::FromCommandLine(&vercon, Cache, cmdline, fallback, helper);
 		return vercon;
 		return vercon;
 	}
 	}
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
-			Version const &fallback) {
+			CacheSetHelper::VerSelector const fallback) {
 		CacheSetHelper helper;
 		CacheSetHelper helper;
 		return FromCommandLine(Cache, cmdline, fallback, helper);
 		return FromCommandLine(Cache, cmdline, fallback, helper);
 	}
 	}
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
-		return FromCommandLine(Cache, cmdline, CANDINST);
+		return FromCommandLine(Cache, cmdline, CacheSetHelper::CANDINST);
 	}
 	}
-
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string const &pkg,
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string const &pkg,
-			Version const &fallback, CacheSetHelper &helper,
+			CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper,
                                            bool const /*onlyFromName = false*/) {
                                            bool const /*onlyFromName = false*/) {
 		VersionContainer vercon;
 		VersionContainer vercon;
 		VersionContainerInterface::FromString(&vercon, Cache, pkg, fallback, helper);
 		VersionContainerInterface::FromString(&vercon, Cache, pkg, fallback, helper);
 		return vercon;
 		return vercon;
 	}
 	}
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg,
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg,
-			Version const &fallback) {
+			CacheSetHelper::VerSelector const fallback) {
 		CacheSetHelper helper;
 		CacheSetHelper helper;
 		return FromString(Cache, pkg, fallback, helper);
 		return FromString(Cache, pkg, fallback, helper);
 	}
 	}
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg) {
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg) {
-		return FromString(Cache, pkg, CANDINST);
+		return FromString(Cache, pkg, CacheSetHelper::CANDINST);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+			Version const &fallback, CacheSetHelper &helper) {
+		VersionContainer vercon;
+		VersionContainerInterface::FromCommandLine(&vercon, Cache, cmdline, (CacheSetHelper::VerSelector)fallback, helper);
+		return vercon;
+	}
+	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+			Version const &fallback) {
+		CacheSetHelper helper;
+		return FromCommandLine(Cache, cmdline, (CacheSetHelper::VerSelector)fallback, helper);
+	}
+	static VersionContainer FromString(pkgCacheFile &Cache, std::string const &pkg,
+			Version const &fallback, CacheSetHelper &helper,
+                                           bool const /*onlyFromName = false*/) {
+		VersionContainer vercon;
+		VersionContainerInterface::FromString(&vercon, Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper);
+		return vercon;
 	}
 	}
+	static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg,
+			Version const &fallback) {
+		CacheSetHelper helper;
+		return FromString(Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 
 
 	/** \brief returns all versions specified for the package
 	/** \brief returns all versions specified for the package
 
 
@@ -605,18 +917,36 @@ public:									/*{{{*/
 	    \param fallback the version(s) you want to get
 	    \param fallback the version(s) you want to get
 	    \param helper the helper used for display and error handling */
 	    \param helper the helper used for display and error handling */
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
-		Version const &fallback, CacheSetHelper &helper) {
+		CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper) {
 		VersionContainer vercon;
 		VersionContainer vercon;
 		VersionContainerInterface::FromPackage(&vercon, Cache, P, fallback, helper);
 		VersionContainerInterface::FromPackage(&vercon, Cache, P, fallback, helper);
 		return vercon;
 		return vercon;
 	}
 	}
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
-					    Version const &fallback) {
+					    CacheSetHelper::VerSelector const fallback) {
 		CacheSetHelper helper;
 		CacheSetHelper helper;
 		return FromPackage(Cache, P, fallback, helper);
 		return FromPackage(Cache, P, fallback, helper);
 	}
 	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+		Version const &fallback, CacheSetHelper &helper) {
+		VersionContainer vercon;
+		VersionContainerInterface::FromPackage(&vercon, Cache, P, (CacheSetHelper::VerSelector)fallback, helper);
+		return vercon;
+	}
+	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+					    Version const &fallback) {
+		CacheSetHelper helper;
+		return FromPackage(Cache, P, (CacheSetHelper::VerSelector)fallback, helper);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P) {
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P) {
-		return FromPackage(Cache, P, CANDIDATE);
+		return FromPackage(Cache, P, CacheSetHelper::CANDIDATE);
 	}
 	}
 
 
 	static std::map<unsigned short, VersionContainer> GroupedFromCommandLine(
 	static std::map<unsigned short, VersionContainer> GroupedFromCommandLine(
@@ -645,26 +975,48 @@ public:									/*{{{*/
 	}
 	}
 
 
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
-					       Version const &selector, CacheSetHelper &helper) {
+					       CacheSetHelper::VerSelector const selector, CacheSetHelper &helper) {
 		VersionContainer vercon;
 		VersionContainer vercon;
 		VersionContainerInterface::FromDependency(&vercon, Cache, D, selector, helper);
 		VersionContainerInterface::FromDependency(&vercon, Cache, D, selector, helper);
 		return vercon;
 		return vercon;
 	}
 	}
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
-					       Version const &selector) {
+					       CacheSetHelper::VerSelector const selector) {
 		CacheSetHelper helper;
 		CacheSetHelper helper;
 		return FromPackage(Cache, D, selector, helper);
 		return FromPackage(Cache, D, selector, helper);
 	}
 	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
+					       Version const &selector, CacheSetHelper &helper) {
+		VersionContainer vercon;
+		VersionContainerInterface::FromDependency(&vercon, Cache, D, (CacheSetHelper::VerSelector)selector, helper);
+		return vercon;
+	}
+	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
+					       Version const &selector) {
+		CacheSetHelper helper;
+		return FromPackage(Cache, D, (CacheSetHelper::VerSelector)selector, helper);
+	}
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) {
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) {
-		return FromPackage(Cache, D, CANDIDATE);
+		return FromPackage(Cache, D, CacheSetHelper::CANDIDATE);
 	}
 	}
 									/*}}}*/
 									/*}}}*/
 };									/*}}}*/
 };									/*}}}*/
-
+// specialisations for push_back containers: std::list & std::vector	/*{{{*/
 template<> template<class Cont> void VersionContainer<std::list<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) {
 template<> template<class Cont> void VersionContainer<std::list<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) {
 	for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v)
 	for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v)
 		_cont.push_back(*v);
 		_cont.push_back(*v);
 }
 }
+template<> template<class Cont> void VersionContainer<std::vector<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) {
+	for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v)
+		_cont.push_back(*v);
+}
 // these two are 'inline' as otherwise the linker has problems with seeing these untemplated
 // these two are 'inline' as otherwise the linker has problems with seeing these untemplated
 // specializations again and again - but we need to see them, so that library users can use them
 // specializations again and again - but we need to see them, so that library users can use them
 template<> inline bool VersionContainer<std::list<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) {
 template<> inline bool VersionContainer<std::list<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) {
@@ -673,11 +1025,29 @@ template<> inline bool VersionContainer<std::list<pkgCache::VerIterator> >::inse
 	_cont.push_back(V);
 	_cont.push_back(V);
 	return true;
 	return true;
 }
 }
+template<> inline bool VersionContainer<std::vector<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) {
+	if (V.end() == true)
+		return false;
+	_cont.push_back(V);
+	return true;
+}
 template<> inline void VersionContainer<std::list<pkgCache::VerIterator> >::insert(const_iterator begin, const_iterator end) {
 template<> inline void VersionContainer<std::list<pkgCache::VerIterator> >::insert(const_iterator begin, const_iterator end) {
 	for (const_iterator v = begin; v != end; ++v)
 	for (const_iterator v = begin; v != end; ++v)
 		_cont.push_back(*v);
 		_cont.push_back(*v);
 }
 }
+template<> inline void VersionContainer<std::vector<pkgCache::VerIterator> >::insert(const_iterator begin, const_iterator end) {
+	for (const_iterator v = begin; v != end; ++v)
+		_cont.push_back(*v);
+}
+									/*}}}*/
+
+template<> template<class Compare> inline bool VersionContainer<std::vector<pkgCache::VerIterator> >::sort(Compare Comp) {
+	std::sort(_cont.begin(), _cont.end(), Comp);
+	return true;
+}
+
 typedef VersionContainer<std::set<pkgCache::VerIterator> > VersionSet;
 typedef VersionContainer<std::set<pkgCache::VerIterator> > VersionSet;
 typedef VersionContainer<std::list<pkgCache::VerIterator> > VersionList;
 typedef VersionContainer<std::list<pkgCache::VerIterator> > VersionList;
+typedef VersionContainer<std::vector<pkgCache::VerIterator> > VersionVector;
 }
 }
 #endif
 #endif

+ 7 - 3
apt-pkg/cdrom.cc

@@ -913,10 +913,14 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-pkgUdevCdromDevices::pkgUdevCdromDevices()                     		/*{{{*/
-   : libudev_handle(NULL)
+pkgUdevCdromDevices::pkgUdevCdromDevices()				/*{{{*/
+: libudev_handle(NULL), udev_new(NULL), udev_enumerate_add_match_property(NULL),
+   udev_enumerate_scan_devices(NULL), udev_enumerate_get_list_entry(NULL),
+   udev_device_new_from_syspath(NULL), udev_enumerate_get_udev(NULL),
+   udev_list_entry_get_name(NULL), udev_device_get_devnode(NULL),
+   udev_enumerate_new(NULL), udev_list_entry_get_next(NULL),
+   udev_device_get_property_value(NULL), udev_enumerate_add_match_sysattr(NULL)
 {
 {
-
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 

+ 4 - 1
apt-pkg/clean.cc

@@ -34,7 +34,10 @@
 bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache)
 bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache)
 {
 {
    bool CleanInstalled = _config->FindB("APT::Clean-Installed",true);
    bool CleanInstalled = _config->FindB("APT::Clean-Installed",true);
-      
+
+   if(Dir == "/")
+      return _error->Error(_("Clean of %s is not supported"), Dir.c_str());
+
    DIR *D = opendir(Dir.c_str());
    DIR *D = opendir(Dir.c_str());
    if (D == 0)
    if (D == 0)
       return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
       return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());

+ 11 - 8
apt-pkg/contrib/cmndline.cc

@@ -47,23 +47,26 @@ CommandLine::~CommandLine()
 char const * CommandLine::GetCommand(Dispatch const * const Map,
 char const * CommandLine::GetCommand(Dispatch const * const Map,
       unsigned int const argc, char const * const * const argv)
       unsigned int const argc, char const * const * const argv)
 {
 {
-   // if there is a -- on the line there must be the word we search for around it
-   // as -- marks the end of the options, just not sure if the command can be
-   // considered an option or not, so accept both
+   // if there is a -- on the line there must be the word we search for either
+   // before it (as -- marks the end of the options) or right after it (as we can't
+   // decide if the command is actually an option, given that in theory, you could
+   // have parameters named like commands)
    for (size_t i = 1; i < argc; ++i)
    for (size_t i = 1; i < argc; ++i)
    {
    {
       if (strcmp(argv[i], "--") != 0)
       if (strcmp(argv[i], "--") != 0)
 	 continue;
 	 continue;
-      ++i;
-      if (i < argc)
+      // check if command is before --
+      for (size_t k = 1; k < i; ++k)
 	 for (size_t j = 0; Map[j].Match != NULL; ++j)
 	 for (size_t j = 0; Map[j].Match != NULL; ++j)
-	    if (strcmp(argv[i], Map[j].Match) == 0)
+	    if (strcmp(argv[k], Map[j].Match) == 0)
 	       return Map[j].Match;
 	       return Map[j].Match;
-      i -= 2;
-      if (i != 0)
+      // see if the next token after -- is the command
+      ++i;
+      if (i < argc)
 	 for (size_t j = 0; Map[j].Match != NULL; ++j)
 	 for (size_t j = 0; Map[j].Match != NULL; ++j)
 	    if (strcmp(argv[i], Map[j].Match) == 0)
 	    if (strcmp(argv[i], Map[j].Match) == 0)
 	       return Map[j].Match;
 	       return Map[j].Match;
+      // we found a --, but not a command
       return NULL;
       return NULL;
    }
    }
    // no --, so search for the first word matching a command
    // no --, so search for the first word matching a command

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

@@ -253,11 +253,6 @@ string Configuration::FindDir(const char *Name,const char *Default) const
 // Configuration::FindVector - Find a vector of values			/*{{{*/
 // Configuration::FindVector - Find a vector of values			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Returns a vector of config values under the given item */
 /* Returns a vector of config values under the given item */
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13)
-vector<string> Configuration::FindVector(const char *Name) const { 
-   return FindVector(Name, ""); 
-}
-#endif
 vector<string> Configuration::FindVector(const char *Name, std::string const &Default) const
 vector<string> Configuration::FindVector(const char *Name, std::string const &Default) const
 {
 {
    vector<string> Vec;
    vector<string> Vec;

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

@@ -34,6 +34,8 @@
 #include <vector>
 #include <vector>
 #include <iostream>
 #include <iostream>
 
 
+#include <apt-pkg/macros.h>
+
 #ifndef APT_8_CLEANER_HEADERS
 #ifndef APT_8_CLEANER_HEADERS
 using std::string;
 using std::string;
 #endif
 #endif
@@ -59,7 +61,7 @@ class Configuration
    
    
    Item *Root;
    Item *Root;
    bool ToFree;
    bool ToFree;
-   
+
    Item *Lookup(Item *Head,const char *S,unsigned long const &Len,bool const &Create);
    Item *Lookup(Item *Head,const char *S,unsigned long const &Len,bool const &Create);
    Item *Lookup(const char *Name,const bool &Create);
    Item *Lookup(const char *Name,const bool &Create);
    inline const Item *Lookup(const char *Name) const
    inline const Item *Lookup(const char *Name) const
@@ -82,12 +84,8 @@ class Configuration
     *
     *
     * \param Name of the parent node
     * \param Name of the parent node
     * \param Default list of values separated by commas */
     * \param Default list of values separated by commas */
-   std::vector<std::string> FindVector(const char *Name, std::string const &Default) const;
-   std::vector<std::string> FindVector(std::string const &Name, std::string const &Default) const { return FindVector(Name.c_str(), Default); };
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13)
-   std::vector<std::string> FindVector(const char *Name) const;
-#endif
-   std::vector<std::string> FindVector(std::string const &Name="") const { return FindVector(Name.c_str(), ""); };
+   std::vector<std::string> FindVector(const char *Name, std::string const &Default = "") const;
+   std::vector<std::string> FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); };
    int FindI(const char *Name,int const &Default = 0) const;
    int FindI(const char *Name,int const &Default = 0) const;
    int FindI(std::string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);};
    int FindI(std::string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);};
    bool FindB(const char *Name,bool const &Default = false) const;
    bool FindB(const char *Name,bool const &Default = false) const;
@@ -127,7 +125,7 @@ class Configuration
    class MatchAgainstConfig
    class MatchAgainstConfig
    {
    {
      std::vector<regex_t *> patterns;
      std::vector<regex_t *> patterns;
-     void clearPatterns();
+     APT_HIDDEN void clearPatterns();
 
 
    public:
    public:
      MatchAgainstConfig(char const * Config);
      MatchAgainstConfig(char const * Config);

+ 101 - 6
apt-pkg/contrib/fileutl.cc

@@ -47,6 +47,8 @@
 #include <signal.h>
 #include <signal.h>
 #include <errno.h>
 #include <errno.h>
 #include <glob.h>
 #include <glob.h>
+#include <pwd.h>
+#include <grp.h>
 
 
 #include <set>
 #include <set>
 #include <algorithm>
 #include <algorithm>
@@ -63,6 +65,10 @@
 #include <endian.h>
 #include <endian.h>
 #include <stdint.h>
 #include <stdint.h>
 
 
+#if __gnu_linux__
+#include <sys/prctl.h>
+#endif
+
 #include <apti18n.h>
 #include <apti18n.h>
 									/*}}}*/
 									/*}}}*/
 
 
@@ -890,7 +896,7 @@ class FileFdPrivate {							/*{{{*/
 	   bool eof;
 	   bool eof;
 	   bool compressing;
 	   bool compressing;
 
 
-	   LZMAFILE() : file(NULL), eof(false), compressing(false) {}
+	   LZMAFILE() : file(NULL), eof(false), compressing(false) { buffer[0] = '\0'; }
 	   ~LZMAFILE() {
 	   ~LZMAFILE() {
 	      if (compressing == true)
 	      if (compressing == true)
 	      {
 	      {
@@ -1278,7 +1284,8 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
 	 if (d->lzma == NULL)
 	 if (d->lzma == NULL)
 	    d->lzma = new FileFdPrivate::LZMAFILE;
 	    d->lzma = new FileFdPrivate::LZMAFILE;
 	 d->lzma->file = (FILE*) compress_struct;
 	 d->lzma->file = (FILE*) compress_struct;
-	 d->lzma->stream = LZMA_STREAM_INIT;
+         lzma_stream tmp_stream = LZMA_STREAM_INIT;
+	 d->lzma->stream = tmp_stream;
 
 
 	 if ((Mode & ReadWrite) == ReadWrite)
 	 if ((Mode & ReadWrite) == ReadWrite)
 	    return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str());
 	    return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str());
@@ -1834,7 +1841,8 @@ static bool StatFileFd(char const * const msg, int const iFd, std::string const
 	 // higher-level code will generate more meaningful messages,
 	 // higher-level code will generate more meaningful messages,
 	 // even translated this would be meaningless for users
 	 // even translated this would be meaningless for users
 	 return _error->Errno("fstat", "Unable to determine %s for fd %i", msg, iFd);
 	 return _error->Errno("fstat", "Unable to determine %s for fd %i", msg, iFd);
-      ispipe = S_ISFIFO(Buf.st_mode);
+      if (FileName.empty() == false)
+	 ispipe = S_ISFIFO(Buf.st_mode);
    }
    }
 
 
    // for compressor pipes st_size is undefined and at 'best' zero
    // for compressor pipes st_size is undefined and at 'best' zero
@@ -2118,10 +2126,8 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)
 
 
    int Pipe[2] = {-1, -1};
    int Pipe[2] = {-1, -1};
    if(pipe(Pipe) != 0)
    if(pipe(Pipe) != 0)
-   {
       return _error->Errno("pipe", _("Failed to create subprocess IPC"));
       return _error->Errno("pipe", _("Failed to create subprocess IPC"));
-      return NULL;
-   }
+
    std::set<int> keep_fds;
    std::set<int> keep_fds;
    keep_fds.insert(Pipe[0]);
    keep_fds.insert(Pipe[0]);
    keep_fds.insert(Pipe[1]);
    keep_fds.insert(Pipe[1]);
@@ -2164,3 +2170,92 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)
 
 
    return true;
    return true;
 }
 }
+
+bool DropPrivs()
+{
+   // uid will be 0 in the end, but gid might be different anyway
+   uid_t old_uid = getuid();
+   gid_t old_gid = getgid();
+
+   if (old_uid != 0)
+      return true;
+   if(_config->FindB("Debug::NoDropPrivs", false) == true)
+      return true;
+
+   const std::string toUser = _config->Find("APT::Sandbox::User", "_apt");
+   struct passwd *pw = getpwnam(toUser.c_str());
+   if (pw == NULL)
+      return _error->Error("No user %s, can not drop rights", toUser.c_str());
+
+#if __gnu_linux__
+   // see prctl(2), needs linux3.5
+   int ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0,0, 0);
+   if(ret < 0)
+      _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret);
+#endif
+   // Do not change the order here, it might break things
+   if (setgroups(1, &pw->pw_gid))
+      return _error->Errno("setgroups", "Failed to setgroups");
+
+   if (setegid(pw->pw_gid) != 0)
+      return _error->Errno("setegid", "Failed to setegid");
+
+   if (setgid(pw->pw_gid) != 0)
+      return _error->Errno("setgid", "Failed to setgid");
+
+   if (setuid(pw->pw_uid) != 0)
+      return _error->Errno("setuid", "Failed to setuid");
+
+   // the seteuid() is probably uneeded (at least thats what the linux
+   // man-page says about setuid(2)) but we cargo culted it anyway
+   if (seteuid(pw->pw_uid) != 0)
+      return _error->Errno("seteuid", "Failed to seteuid");
+
+   // Verify that the user has only a single group, and the correct one
+   gid_t groups[1];
+   if (getgroups(1, groups) != 1)
+      return _error->Errno("getgroups", "Could not get new groups");
+   if (groups[0] != pw->pw_gid)
+      return _error->Error("Could not switch group");
+
+   // Verify that gid, egid, uid, and euid changed
+   if (getgid() != pw->pw_gid)
+      return _error->Error("Could not switch group");
+   if (getegid() != pw->pw_gid)
+      return _error->Error("Could not switch effective group");
+   if (getuid() != pw->pw_uid)
+      return _error->Error("Could not switch user");
+   if (geteuid() != pw->pw_uid)
+      return _error->Error("Could not switch effective user");
+
+#ifdef HAVE_GETRESUID
+   // verify that the saved set-user-id was changed as well
+   uid_t ruid = 0;
+   uid_t euid = 0;
+   uid_t suid = 0;
+   if (getresuid(&ruid, &euid, &suid))
+      return _error->Errno("getresuid", "Could not get saved set-user-ID");
+   if (suid != pw->pw_uid)
+      return _error->Error("Could not switch saved set-user-ID");
+#endif
+
+#ifdef HAVE_GETRESGID
+   // verify that the saved set-group-id was changed as well
+   gid_t rgid = 0;
+   gid_t egid = 0;
+   gid_t sgid = 0;
+   if (getresgid(&rgid, &egid, &sgid))
+      return _error->Errno("getresuid", "Could not get saved set-group-ID");
+   if (sgid != pw->pw_gid)
+      return _error->Error("Could not switch saved set-group-ID");
+#endif
+
+   // Check that uid and gid changes do not work anymore
+   if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1))
+      return _error->Error("Could restore a gid to root, privilege dropping did not work");
+
+   if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
+      return _error->Error("Could restore a uid to root, privilege dropping did not work");
+
+   return true;
+}

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

@@ -85,7 +85,9 @@ class FileFd
    bool Skip(unsigned long long To);
    bool Skip(unsigned long long To);
    bool Truncate(unsigned long long To);
    bool Truncate(unsigned long long To);
    unsigned long long Tell();
    unsigned long long Tell();
+   // the size of the file content (compressed files will be uncompressed first)
    unsigned long long Size();
    unsigned long long Size();
+   // the size of the file itself
    unsigned long long FileSize();
    unsigned long long FileSize();
    time_t ModificationTime();
    time_t ModificationTime();
 
 
@@ -193,9 +195,23 @@ pid_t ExecFork(std::set<int> keep_fds);
 void MergeKeepFdsFromConfiguration(std::set<int> &keep_fds);
 void MergeKeepFdsFromConfiguration(std::set<int> &keep_fds);
 bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
 bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
 
 
+
 // check if the given file starts with a PGP cleartext signature
 // check if the given file starts with a PGP cleartext signature
 bool StartsWithGPGClearTextSignature(std::string const &FileName);
 bool StartsWithGPGClearTextSignature(std::string const &FileName);
 
 
+/**
+ * \brief Drop privileges
+ *
+ * Drop the privileges to the user _apt (or the one specified in
+ * APT::Sandbox::User). This does not set the supplementary group
+ * ids up correctly, it only uses the default group. Also prevent
+ * the process from gaining any new privileges afterwards, at least
+ * on Linux.
+ *
+ * \return true on success, false on failure with _error set
+ */
+bool DropPrivs();
+
 // File string manipulators
 // File string manipulators
 std::string flNotDir(std::string File);
 std::string flNotDir(std::string File);
 std::string flNotFile(std::string File);
 std::string flNotFile(std::string File);

+ 18 - 45
apt-pkg/contrib/gpgv.cc

@@ -32,50 +32,30 @@ static char * GenerateTemporaryFileTemplate(const char *basename)	/*{{{*/
 									/*}}}*/
 									/*}}}*/
 // ExecGPGV - returns the command needed for verify			/*{{{*/
 // ExecGPGV - returns the command needed for verify			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Generating the commandline for calling gpgv is somehow complicated as
+/* Generating the commandline for calling gpg is somehow complicated as
    we need to add multiple keyrings and user supplied options.
    we need to add multiple keyrings and user supplied options.
-   Also, as gpgv has no options to enforce a certain reduced style of
+   Also, as gpg has no options to enforce a certain reduced style of
    clear-signed files (=the complete content of the file is signed and
    clear-signed files (=the complete content of the file is signed and
    the content isn't encoded) we do a divide and conquer approach here
    the content isn't encoded) we do a divide and conquer approach here
-   and split up the clear-signed file in message and signature for gpgv
+   and split up the clear-signed file in message and signature for gpg.
+   And as a cherry on the cake, we use our apt-key wrapper to do part
+   of the lifting in regards to merging keyrings. Fun for the whole family.
 */
 */
 void ExecGPGV(std::string const &File, std::string const &FileGPG,
 void ExecGPGV(std::string const &File, std::string const &FileGPG,
              int const &statusfd, int fd[2])
              int const &statusfd, int fd[2])
 {
 {
    #define EINTERNAL 111
    #define EINTERNAL 111
-   std::string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
-   // FIXME: remove support for deprecated APT::GPGV setting
-   std::string const trustedFile = _config->Find("APT::GPGV::TrustedKeyring", _config->FindFile("Dir::Etc::Trusted"));
-   std::string const trustedPath = _config->FindDir("Dir::Etc::TrustedParts");
+   std::string const aptkey = _config->FindFile("Dir::Bin::apt-key", "/usr/bin/apt-key");
 
 
    bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
    bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
 
 
-   if (Debug == true)
-   {
-      std::clog << "gpgv path: " << gpgvpath << std::endl;
-      std::clog << "Keyring file: " << trustedFile << std::endl;
-      std::clog << "Keyring path: " << trustedPath << std::endl;
-   }
-
-   std::vector<std::string> keyrings;
-   if (DirectoryExists(trustedPath))
-     keyrings = GetListOfFilesInDir(trustedPath, "gpg", false, true);
-   if (RealFileExists(trustedFile) == true)
-     keyrings.push_back(trustedFile);
-
    std::vector<const char *> Args;
    std::vector<const char *> Args;
-   Args.reserve(30);
-
-   if (keyrings.empty() == true)
-   {
-      // TRANSLATOR: %s is the trusted keyring parts directory
-      ioprintf(std::cerr, _("No keyring installed in %s."),
-	    _config->FindDir("Dir::Etc::TrustedParts").c_str());
-      exit(EINTERNAL);
-   }
+   Args.reserve(10);
 
 
-   Args.push_back(gpgvpath.c_str());
-   Args.push_back("--ignore-time-conflict");
+   Args.push_back(aptkey.c_str());
+   Args.push_back("--quiet");
+   Args.push_back("--readonly");
+   Args.push_back("verify");
 
 
    char statusfdstr[10];
    char statusfdstr[10];
    if (statusfd != -1)
    if (statusfd != -1)
@@ -85,13 +65,6 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       Args.push_back(statusfdstr);
       Args.push_back(statusfdstr);
    }
    }
 
 
-   for (std::vector<std::string>::const_iterator K = keyrings.begin();
-	K != keyrings.end(); ++K)
-   {
-      Args.push_back("--keyring");
-      Args.push_back(K->c_str());
-   }
-
    Configuration::Item const *Opts;
    Configuration::Item const *Opts;
    Opts = _config->Tree("Acquire::gpgv::Options");
    Opts = _config->Tree("Acquire::gpgv::Options");
    if (Opts != 0)
    if (Opts != 0)
@@ -160,7 +133,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
 
 
    if (Debug == true)
    if (Debug == true)
    {
    {
-      std::clog << "Preparing to exec: " << gpgvpath;
+      std::clog << "Preparing to exec: ";
       for (std::vector<const char *>::const_iterator a = Args.begin(); *a != NULL; ++a)
       for (std::vector<const char *>::const_iterator a = Args.begin(); *a != NULL; ++a)
 	 std::clog << " " << *a;
 	 std::clog << " " << *a;
       std::clog << std::endl;
       std::clog << std::endl;
@@ -168,7 +141,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
 
 
    if (statusfd != -1)
    if (statusfd != -1)
    {
    {
-      int const nullfd = open("/dev/null", O_RDONLY);
+      int const nullfd = open("/dev/null", O_WRONLY);
       close(fd[0]);
       close(fd[0]);
       // Redirect output to /dev/null; we read from the status fd
       // Redirect output to /dev/null; we read from the status fd
       if (statusfd != STDOUT_FILENO)
       if (statusfd != STDOUT_FILENO)
@@ -185,7 +158,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
 
 
    if (releaseSignature == DETACHED)
    if (releaseSignature == DETACHED)
    {
    {
-      execvp(gpgvpath.c_str(), (char **) &Args[0]);
+      execvp(Args[0], (char **) &Args[0]);
       ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
       ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
       exit(EINTERNAL);
       exit(EINTERNAL);
    }
    }
@@ -205,7 +178,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       {
       {
 	 if (statusfd != -1)
 	 if (statusfd != -1)
 	    dup2(fd[1], statusfd);
 	    dup2(fd[1], statusfd);
-	 execvp(gpgvpath.c_str(), (char **) &Args[0]);
+	 execvp(Args[0], (char **) &Args[0]);
 	 ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
 	 ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
 	 UNLINK_EXIT(EINTERNAL);
 	 UNLINK_EXIT(EINTERNAL);
       }
       }
@@ -216,7 +189,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       {
       {
 	 if (errno == EINTR)
 	 if (errno == EINTR)
 	    continue;
 	    continue;
-	 ioprintf(std::cerr, _("Waited for %s but it wasn't there"), "gpgv");
+	 ioprintf(std::cerr, _("Waited for %s but it wasn't there"), "apt-key");
 	 UNLINK_EXIT(EINTERNAL);
 	 UNLINK_EXIT(EINTERNAL);
       }
       }
 #undef UNLINK_EXIT
 #undef UNLINK_EXIT
@@ -229,14 +202,14 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       // check if it exit'ed normally …
       // check if it exit'ed normally …
       if (WIFEXITED(Status) == false)
       if (WIFEXITED(Status) == false)
       {
       {
-	 ioprintf(std::cerr, _("Sub-process %s exited unexpectedly"), "gpgv");
+	 ioprintf(std::cerr, _("Sub-process %s exited unexpectedly"), "apt-key");
 	 exit(EINTERNAL);
 	 exit(EINTERNAL);
       }
       }
 
 
       // … and with a good exit code
       // … and with a good exit code
       if (WEXITSTATUS(Status) != 0)
       if (WEXITSTATUS(Status) != 0)
       {
       {
-	 ioprintf(std::cerr, _("Sub-process %s returned an error code (%u)"), "gpgv", WEXITSTATUS(Status));
+	 ioprintf(std::cerr, _("Sub-process %s returned an error code (%u)"), "apt-key", WEXITSTATUS(Status));
 	 exit(WEXITSTATUS(Status));
 	 exit(WEXITSTATUS(Status));
       }
       }
 
 

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

@@ -209,11 +209,11 @@ bool HashStringList::operator==(HashStringList const &other) const	/*{{{*/
    std::string const forcedType = _config->Find("Acquire::ForceHash", "");
    std::string const forcedType = _config->Find("Acquire::ForceHash", "");
    if (forcedType.empty() == false)
    if (forcedType.empty() == false)
    {
    {
-      HashString const * const hs = other.find(forcedType);
+      HashString const * const hs = find(forcedType);
       HashString const * const ohs = other.find(forcedType);
       HashString const * const ohs = other.find(forcedType);
       if (hs == NULL || ohs == NULL)
       if (hs == NULL || ohs == NULL)
 	 return false;
 	 return false;
-      return hs == ohs;
+      return *hs == *ohs;
    }
    }
    short matches = 0;
    short matches = 0;
    for (const_iterator hs = begin(); hs != end(); ++hs)
    for (const_iterator hs = begin(); hs != end(); ++hs)

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

@@ -138,7 +138,7 @@
 // Non-ABI-Breaks should only increase RELEASE number.
 // Non-ABI-Breaks should only increase RELEASE number.
 // See also buildlib/libversion.mak
 // See also buildlib/libversion.mak
 #define APT_PKG_MAJOR 4
 #define APT_PKG_MAJOR 4
-#define APT_PKG_MINOR 13
+#define APT_PKG_MINOR 14
 #define APT_PKG_RELEASE 0
 #define APT_PKG_RELEASE 0
 
 
 #endif
 #endif

+ 86 - 0
apt-pkg/contrib/proxy.cc

@@ -0,0 +1,86 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/* ######################################################################
+   
+   Proxy - Proxy releated functions
+   
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#include<apt-pkg/configuration.h>
+#include<apt-pkg/error.h>
+#include<apt-pkg/fileutl.h>
+#include<apt-pkg/strutl.h>
+
+#include<iostream>
+#include <unistd.h>
+
+#include "proxy.h"
+
+
+// AutoDetectProxy - auto detect proxy          			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool AutoDetectProxy(URI &URL)
+{
+   // we support both http/https debug options
+   bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false);
+
+   // the user already explicitly set a proxy for this host
+   if(_config->Find("Acquire::"+URL.Access+"::proxy::"+URL.Host, "") != "")
+      return true;
+
+   // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
+   // name without the dash ("-")
+   std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect",
+                                      _config->Find("Acquire::"+URL.Access+"::ProxyAutoDetect"));
+
+   if (AutoDetectProxyCmd.empty())
+      return true;
+
+   if (Debug)
+      std::clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << std::endl;
+
+   int Pipes[2] = {-1,-1};
+   if (pipe(Pipes) != 0)
+      return _error->Errno("pipe", "Failed to create Pipe");
+
+   pid_t Process = ExecFork();
+   if (Process == 0)
+   {
+      close(Pipes[0]);
+      dup2(Pipes[1],STDOUT_FILENO);
+      SetCloseExec(STDOUT_FILENO,false);
+
+      std::string foo = URL;
+      const char *Args[4];
+      Args[0] = AutoDetectProxyCmd.c_str();
+      Args[1] = foo.c_str();
+      Args[2] = 0;
+      execv(Args[0],(char **)Args);
+      std::cerr << "Failed to exec method " << Args[0] << std::endl;
+      _exit(100);
+   }
+   char buf[512];
+   int InFd = Pipes[0];
+   close(Pipes[1]);
+   int res = read(InFd, buf, sizeof(buf)-1);
+   ExecWait(Process, "ProxyAutoDetect", true);
+
+   if (res < 0)
+      return _error->Errno("read", "Failed to read");
+   if (res == 0)
+      return _error->Warning("ProxyAutoDetect returned no data");
+
+   // add trailing \0
+   buf[res] = 0;
+
+   if (Debug)
+      std::clog << "auto detect command returned: '" << buf << "'" << std::endl;
+
+   if (strstr(buf, URL.Access.c_str()) == buf)
+      _config->Set("Acquire::"+URL.Access+"::proxy::"+URL.Host, _strstrip(buf));
+
+   return true;
+}
+									/*}}}*/

+ 16 - 0
apt-pkg/contrib/proxy.h

@@ -0,0 +1,16 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/* ######################################################################
+   
+   Proxy - Proxy operations
+   
+   ##################################################################### */
+									/*}}}*/
+#ifndef PKGLIB_PROXY_H
+#define PKGLIB_PROXY_H
+
+class URI;
+bool AutoDetectProxy(URI &URL);
+
+
+#endif

+ 63 - 17
apt-pkg/contrib/strutl.cc

@@ -45,14 +45,26 @@ using namespace std;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 namespace APT {
 namespace APT {
    namespace String {
    namespace String {
-std::string Strip(const std::string &s)
+std::string Strip(const std::string &str)
 {
 {
-   size_t start = s.find_first_not_of(" \t\n");
-   // only whitespace
-   if (start == string::npos)
+   // ensure we have at least one character
+   if (str.empty() == true)
+      return str;
+
+   char const * const s = str.c_str();
+   size_t start = 0;
+   for (; isspace(s[start]) != 0; ++start)
+      ; // find the first not-space
+
+   // string contains only whitespaces
+   if (s[start] == '\0')
       return "";
       return "";
-   size_t end = s.find_last_not_of(" \t\n");
-   return s.substr(start, end-start+1);
+
+   size_t end = str.length() - 1;
+   for (; isspace(s[end]) != 0; --end)
+      ; // find the last not-space
+
+   return str.substr(start, end - start + 1);
 }
 }
 
 
 bool Endswith(const std::string &s, const std::string &end)
 bool Endswith(const std::string &s, const std::string &end)
@@ -62,6 +74,13 @@ bool Endswith(const std::string &s, const std::string &end)
    return (s.substr(s.size() - end.size(), s.size()) == end);
    return (s.substr(s.size() - end.size(), s.size()) == end);
 }
 }
 
 
+bool Startswith(const std::string &s, const std::string &start)
+{
+   if (start.size() > s.size())
+      return false;
+   return (s.substr(0, start.size()) == start);
+}
+
 }
 }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -434,23 +453,30 @@ string TimeToStr(unsigned long Sec)
 /* This replaces all occurrences of Subst with Contents in Str. */
 /* This replaces all occurrences of Subst with Contents in Str. */
 string SubstVar(const string &Str,const string &Subst,const string &Contents)
 string SubstVar(const string &Str,const string &Subst,const string &Contents)
 {
 {
+   if (Subst.empty() == true)
+      return Str;
+
    string::size_type Pos = 0;
    string::size_type Pos = 0;
    string::size_type OldPos = 0;
    string::size_type OldPos = 0;
    string Temp;
    string Temp;
-   
-   while (OldPos < Str.length() && 
+
+   while (OldPos < Str.length() &&
 	  (Pos = Str.find(Subst,OldPos)) != string::npos)
 	  (Pos = Str.find(Subst,OldPos)) != string::npos)
    {
    {
-      Temp += string(Str,OldPos,Pos) + Contents;
-      OldPos = Pos + Subst.length();      
+      if (OldPos != Pos)
+	 Temp.append(Str, OldPos, Pos - OldPos);
+      if (Contents.empty() == false)
+	 Temp.append(Contents);
+      OldPos = Pos + Subst.length();
    }
    }
-   
+
    if (OldPos == 0)
    if (OldPos == 0)
       return Str;
       return Str;
-   
+
+   if (OldPos >= Str.length())
+      return Temp;
    return Temp + string(Str,OldPos);
    return Temp + string(Str,OldPos);
 }
 }
-
 string SubstVar(string Str,const struct SubstVar *Vars)
 string SubstVar(string Str,const struct SubstVar *Vars)
 {
 {
    for (; Vars->Subst != 0; Vars++)
    for (; Vars->Subst != 0; Vars++)
@@ -697,9 +723,12 @@ string LookupTag(const string &Message,const char *Tag,const char *Default)
    then returns the result. Several varients on true/false are checked. */
    then returns the result. Several varients on true/false are checked. */
 int StringToBool(const string &Text,int Default)
 int StringToBool(const string &Text,int Default)
 {
 {
-   char *End;
-   int Res = strtol(Text.c_str(),&End,0);   
-   if (End != Text.c_str() && Res >= 0 && Res <= 1)
+   char *ParseEnd;
+   int Res = strtol(Text.c_str(),&ParseEnd,0);
+   // ensure that the entire string was converted by strtol to avoid
+   // failures on "apt-cache show -a 0ad" where the "0" is converted
+   const char *TextEnd = Text.c_str()+Text.size();
+   if (ParseEnd == TextEnd && Res >= 0 && Res <= 1)
       return Res;
       return Res;
    
    
    // Check for positives
    // Check for positives
@@ -1039,7 +1068,7 @@ bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is used in decoding the 256bit encoded fixed length fields in
 /* This is used in decoding the 256bit encoded fixed length fields in
    tar files */
    tar files */
-bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
+bool Base256ToNum(const char *Str,unsigned long long &Res,unsigned int Len)
 {
 {
    if ((Str[0] & 0x80) == 0)
    if ((Str[0] & 0x80) == 0)
       return false;
       return false;
@@ -1052,6 +1081,23 @@ bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
+// Base256ToNum - Convert a fixed length binary to a number             /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used in decoding the 256bit encoded fixed length fields in
+   tar files */
+bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
+{
+   unsigned long long Num;
+   bool rc;
+
+   rc = Base256ToNum(Str, Num, Len);
+   Res = Num;
+   if (Res != Num)
+      return false;
+
+   return rc;
+}
+									/*}}}*/
 // HexDigit - Convert a hex character into an integer			/*{{{*/
 // HexDigit - Convert a hex character into an integer			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Helper for Hex2Num */
 /* Helper for Hex2Num */

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

@@ -40,6 +40,7 @@ namespace APT {
    namespace String {
    namespace String {
       std::string Strip(const std::string &s);
       std::string Strip(const std::string &s);
       bool Endswith(const std::string &s, const std::string &ending);
       bool Endswith(const std::string &s, const std::string &ending);
+      bool Startswith(const std::string &s, const std::string &starting);
    }
    }
 }
 }
 
 
@@ -72,6 +73,7 @@ bool ReadMessages(int Fd, std::vector<std::string> &List);
 bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0);
 bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0);
 bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base = 0);
 bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base = 0);
 bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len);
 bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len);
+bool Base256ToNum(const char *Str,unsigned long long &Res,unsigned int Len);
 bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length);
 bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length);
 
 
 // input changing string split
 // input changing string split
@@ -151,9 +153,9 @@ inline const char *DeNull(const char *s) {return (s == 0?"(null)":s);}
 class URI
 class URI
 {
 {
    void CopyFrom(const std::string &From);
    void CopyFrom(const std::string &From);
-		 
+
    public:
    public:
-   
+
    std::string Access;
    std::string Access;
    std::string User;
    std::string User;
    std::string Password;
    std::string Password;

+ 61 - 35
apt-pkg/deb/debindexfile.cc

@@ -81,14 +81,18 @@ pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
 {
 {
    string SourcesURI = _config->FindDir("Dir::State::lists") + 
    string SourcesURI = _config->FindDir("Dir::State::lists") + 
       URItoFileName(IndexURI("Sources"));
       URItoFileName(IndexURI("Sources"));
-   string SourcesURIgzip = SourcesURI + ".gz";
 
 
-   if (!FileExists(SourcesURI) && !FileExists(SourcesURIgzip))
-      return NULL;
-   else if (!FileExists(SourcesURI) && FileExists(SourcesURIgzip))
-      SourcesURI = SourcesURIgzip;
-
-   return new debSrcRecordParser(SourcesURI,this);
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+   {
+      string p;
+      p = SourcesURI + '.' + *t;
+      if (FileExists(p))
+         return new debSrcRecordParser(p, this);
+   }
+   if (FileExists(SourcesURI))
+      return new debSrcRecordParser(SourcesURI, this);
+   return NULL;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // SourcesIndex::Describe - Give a descriptive path to the index	/*{{{*/
 // SourcesIndex::Describe - Give a descriptive path to the index	/*{{{*/
@@ -127,14 +131,18 @@ string debSourcesIndex::Info(const char *Type) const
 // SourcesIndex::Index* - Return the URI to the index files		/*{{{*/
 // SourcesIndex::Index* - Return the URI to the index files		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-inline string debSourcesIndex::IndexFile(const char *Type) const
+string debSourcesIndex::IndexFile(const char *Type) const
 {
 {
    string s = URItoFileName(IndexURI(Type));
    string s = URItoFileName(IndexURI(Type));
-   string sgzip = s + ".gz";
-   if (!FileExists(s) && FileExists(sgzip))
-       return sgzip;
-   else
-       return s;
+
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+   {
+      string p = s + '.' + *t;
+      if (FileExists(p))
+         return p;
+   }
+   return s;
 }
 }
 
 
 string debSourcesIndex::IndexURI(const char *Type) const
 string debSourcesIndex::IndexURI(const char *Type) const
@@ -257,14 +265,18 @@ string debPackagesIndex::Info(const char *Type) const
 // PackagesIndex::Index* - Return the URI to the index files		/*{{{*/
 // PackagesIndex::Index* - Return the URI to the index files		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-inline string debPackagesIndex::IndexFile(const char *Type) const
+string debPackagesIndex::IndexFile(const char *Type) const
 {
 {
    string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
    string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
-   string sgzip = s + ".gz";
-   if (!FileExists(s) && FileExists(sgzip))
-       return sgzip;
-   else
-       return s;
+
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+   {
+      string p = s + '.' + *t;
+      if (FileExists(p))
+         return p;
+   }
+   return s;
 }
 }
 string debPackagesIndex::IndexURI(const char *Type) const
 string debPackagesIndex::IndexURI(const char *Type) const
 {
 {
@@ -409,14 +421,18 @@ debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section
 // TranslationIndex::Trans* - Return the URI to the translation files	/*{{{*/
 // TranslationIndex::Trans* - Return the URI to the translation files	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-inline string debTranslationsIndex::IndexFile(const char *Type) const
+string debTranslationsIndex::IndexFile(const char *Type) const
 {
 {
    string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
    string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
-   string sgzip = s + ".gz";
-   if (!FileExists(s) && FileExists(sgzip))
-       return sgzip;
-   else
-       return s;
+
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+   {
+      string p = s + '.' + *t;
+      if (FileExists(p))
+         return p;
+   }
+   return s;
 }
 }
 string debTranslationsIndex::IndexURI(const char *Type) const
 string debTranslationsIndex::IndexURI(const char *Type) const
 {
 {
@@ -619,7 +635,7 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
    CFile->Size = Pkg.FileSize();
    CFile->Size = Pkg.FileSize();
    CFile->mtime = Pkg.ModificationTime();
    CFile->mtime = Pkg.ModificationTime();
-   map_ptrloc const storage = Gen.WriteUniqString("now");
+   map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
    CFile->Archive = storage;
    CFile->Archive = storage;
    
    
    if (Gen.MergeList(Parser) == false)
    if (Gen.MergeList(Parser) == false)
@@ -692,15 +708,27 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
 
 
    // get the control data out of the deb file vid dpkg -I
    // get the control data out of the deb file vid dpkg -I
    // ... can I haz libdpkg?
    // ... can I haz libdpkg?
+   Configuration::Item const *Opts = _config->Tree("DPkg::Options");
    std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg");
    std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg");
-   const char *Args[5] = {dpkg.c_str(),
-                          "-I",
-                          DebFile.c_str(),
-                          "control",
-                          NULL};
+   std::vector<const char *> Args;
+   Args.push_back(dpkg.c_str());
+   if (Opts != 0)
+   {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+      {
+	 if (Opts->Value.empty() == true)
+	    continue;
+	 Args.push_back(Opts->Value.c_str());
+      }
+   }
+   Args.push_back("-I");
+   Args.push_back(DebFile.c_str());
+   Args.push_back("control");
+   Args.push_back(NULL);
    FileFd PipeFd;
    FileFd PipeFd;
    pid_t Child;
    pid_t Child;
-   if(Popen(Args, PipeFd, Child, FileFd::ReadOnly) == false)
+   if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
       return _error->Error("Popen failed");
       return _error->Error("Popen failed");
    // FIXME: static buffer
    // FIXME: static buffer
    char buf[8*1024];
    char buf[8*1024];
@@ -710,7 +738,7 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
    ExecWait(Child, "Popen");
    ExecWait(Child, "Popen");
 
 
    // now write the control data to a tempfile
    // now write the control data to a tempfile
-   SPtr<FileFd> DebControl = GetTempFile("deb-file-" + DebFile);
+   SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
    if(DebControl == NULL)
    if(DebControl == NULL)
       return false;
       return false;
    DebControl->Write(buf, n);
    DebControl->Write(buf, n);
@@ -738,8 +766,6 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
 }
 }
 pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
 pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
 {
 {
-   // FIXME: we could simply always return pkgCache::PkgFileIterator(Cache);
-   //        to indicate its never in the cache which will force a Merge()
    pkgCache::PkgFileIterator File = Cache.FileBegin();
    pkgCache::PkgFileIterator File = Cache.FileBegin();
    for (; File.end() == false; ++File)
    for (; File.end() == false; ++File)
    {
    {

+ 13 - 12
apt-pkg/deb/debindexfile.h

@@ -65,10 +65,10 @@ class debPackagesIndex : public pkgIndexFile
    std::string Section;
    std::string Section;
    std::string Architecture;
    std::string Architecture;
 
 
-   std::string Info(const char *Type) const;
-   std::string IndexFile(const char *Type) const;
-   std::string IndexURI(const char *Type) const;
-   
+   APT_HIDDEN std::string Info(const char *Type) const;
+   APT_HIDDEN std::string IndexFile(const char *Type) const;
+   APT_HIDDEN std::string IndexURI(const char *Type) const;
+
    public:
    public:
    
    
    virtual const Type *GetType() const APT_CONST;
    virtual const Type *GetType() const APT_CONST;
@@ -102,11 +102,11 @@ class debTranslationsIndex : public pkgIndexFile
    std::string Section;
    std::string Section;
    const char * const Language;
    const char * const Language;
    
    
-   std::string Info(const char *Type) const;
-   std::string IndexFile(const char *Type) const;
-   std::string IndexURI(const char *Type) const;
+   APT_HIDDEN std::string Info(const char *Type) const;
+   APT_HIDDEN std::string IndexFile(const char *Type) const;
+   APT_HIDDEN std::string IndexURI(const char *Type) const;
 
 
-   inline std::string TranslationFile() const {return std::string("Translation-").append(Language);};
+   APT_HIDDEN std::string TranslationFile() const {return std::string("Translation-").append(Language);};
 
 
    public:
    public:
    
    
@@ -136,10 +136,10 @@ class debSourcesIndex : public pkgIndexFile
    std::string Dist;
    std::string Dist;
    std::string Section;
    std::string Section;
 
 
-   std::string Info(const char *Type) const;
-   std::string IndexFile(const char *Type) const;
-   std::string IndexURI(const char *Type) const;
-   
+   APT_HIDDEN std::string Info(const char *Type) const;
+   APT_HIDDEN std::string IndexFile(const char *Type) const;
+   APT_HIDDEN std::string IndexURI(const char *Type) const;
+
    public:
    public:
 
 
    virtual const Type *GetType() const APT_CONST;
    virtual const Type *GetType() const APT_CONST;
@@ -214,6 +214,7 @@ class debDscFileIndex : public pkgIndexFile
 
 
 class debDebianSourceDirIndex : public debDscFileIndex
 class debDebianSourceDirIndex : public debDscFileIndex
 {
 {
+ public:
    virtual const Type *GetType() const APT_CONST;
    virtual const Type *GetType() const APT_CONST;
 };
 };
 
 

+ 73 - 31
apt-pkg/deb/deblistparser.cc

@@ -58,18 +58,6 @@ debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
    MultiArchEnabled = Architectures.size() > 1;
    MultiArchEnabled = Architectures.size() > 1;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// ListParser::UniqFindTagWrite - Find the tag and write a unq string	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-unsigned long debListParser::UniqFindTagWrite(const char *Tag)
-{
-   const char *Start;
-   const char *Stop;
-   if (Section.Find(Tag,Start,Stop) == false)
-      return 0;
-   return WriteUniqString(Start,Stop - Start);
-}
-									/*}}}*/
 // ListParser::Package - Return the package name			/*{{{*/
 // ListParser::Package - Return the package name			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is to return the name of the package this section describes */
 /* This is to return the name of the package this section describes */
@@ -108,7 +96,7 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors)	/*{{{*/
 {
 {
    unsigned char MA;
    unsigned char MA;
    string const MultiArch = Section.FindS("Multi-Arch");
    string const MultiArch = Section.FindS("Multi-Arch");
-   if (MultiArch.empty() == true)
+   if (MultiArch.empty() == true || MultiArch == "no")
       MA = pkgCache::Version::None;
       MA = pkgCache::Version::None;
    else if (MultiArch == "same") {
    else if (MultiArch == "same") {
       if (ArchitectureAll() == true)
       if (ArchitectureAll() == true)
@@ -144,8 +132,67 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors)	/*{{{*/
 /* */
 /* */
 bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
 bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
 {
 {
+   const char *Start;
+   const char *Stop;
+
    // Parse the section
    // Parse the section
-   Ver->Section = UniqFindTagWrite("Section");
+   if (Section.Find("Section",Start,Stop) == true)
+   {
+      map_stringitem_t const idx = StoreString(pkgCacheGenerator::SECTION, Start, Stop - Start);
+      Ver->Section = idx;
+   }
+   // Parse the source package name
+   pkgCache::GrpIterator const G = Ver.ParentPkg().Group();
+   Ver->SourcePkgName = G->Name;
+   Ver->SourceVerStr = Ver->VerStr;
+   if (Section.Find("Source",Start,Stop) == true)
+   {
+      const char * const Space = (const char * const) memchr(Start, ' ', Stop - Start);
+      pkgCache::VerIterator V;
+
+      if (Space != NULL)
+      {
+	 Stop = Space;
+	 const char * const Open = (const char * const) memchr(Space, '(', Stop - Space);
+	 if (likely(Open != NULL))
+	 {
+	    const char * const Close = (const char * const) memchr(Open, ')', Stop - Open);
+	    if (likely(Close != NULL))
+	    {
+	       std::string const version(Open + 1, (Close - Open) - 1);
+	       if (version != Ver.VerStr())
+	       {
+		  map_stringitem_t const idx = StoreString(pkgCacheGenerator::VERSIONNUMBER, version);
+		  Ver->SourceVerStr = idx;
+	       }
+	    }
+	 }
+      }
+
+      std::string const pkgname(Start, Stop - Start);
+      if (pkgname != G.Name())
+      {
+	 for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P))
+	 {
+	    for (V = P.VersionList(); V.end() == false; ++V)
+	    {
+	       if (pkgname == V.SourcePkgName())
+	       {
+		  Ver->SourcePkgName = V->SourcePkgName;
+		  break;
+	       }
+	    }
+	    if (V.end() == false)
+	       break;
+	 }
+	 if (V.end() == true)
+	 {
+	    map_stringitem_t const idx = StoreString(pkgCacheGenerator::PKGNAME, pkgname);
+	    Ver->SourcePkgName = idx;
+	 }
+      }
+   }
+
    Ver->MultiArch = ParseMultiArch(true);
    Ver->MultiArch = ParseMultiArch(true);
    // Archive Size
    // Archive Size
    Ver->Size = Section.FindULL("Size");
    Ver->Size = Section.FindULL("Size");
@@ -154,10 +201,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
    Ver->InstalledSize *= 1024;
    Ver->InstalledSize *= 1024;
 
 
    // Priority
    // Priority
-   const char *Start;
-   const char *Stop;
    if (Section.Find("Priority",Start,Stop) == true)
    if (Section.Find("Priority",Start,Stop) == true)
-   {      
+   {
       if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
       if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
 	 Ver->Priority = pkgCache::State::Extra;
 	 Ver->Priority = pkgCache::State::Extra;
    }
    }
@@ -255,9 +300,6 @@ MD5SumValue debListParser::Description_md5()
 bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
 bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
 			       pkgCache::VerIterator &Ver)
 			       pkgCache::VerIterator &Ver)
 {
 {
-   if (Pkg->Section == 0)
-      Pkg->Section = UniqFindTagWrite("Section");
-
    string const static myArch = _config->Find("APT::Architecture");
    string const static myArch = _config->Find("APT::Architecture");
    // Possible values are: "all", "native", "installed" and "none"
    // Possible values are: "all", "native", "installed" and "none"
    // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
    // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
@@ -795,8 +837,8 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 	 Start = ParseDepends(Start,Stop,Package,Version,Op);
 	 Start = ParseDepends(Start,Stop,Package,Version,Op);
 	 if (Start == 0)
 	 if (Start == 0)
 	    return _error->Error("Problem parsing Provides line");
 	    return _error->Error("Problem parsing Provides line");
-	 if (Op != pkgCache::Dep::NoOp) {
-	    _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str());
+	 if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) {
+	    _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str());
 	 } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
 	 } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
 	    if (NewProvidesAllArch(Ver, Package, Version) == false)
 	    if (NewProvidesAllArch(Ver, Package, Version) == false)
 	       return false;
 	       return false;
@@ -893,7 +935,7 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
 {
 {
    // apt-secure does no longer download individual (per-section) Release
    // apt-secure does no longer download individual (per-section) Release
    // file. to provide Component pinning we use the section name now
    // file. to provide Component pinning we use the section name now
-   map_ptrloc const storage = WriteUniqString(component);
+   map_stringitem_t const storage = StoreString(pkgCacheGenerator::MIXED, component);
    FileI->Component = storage;
    FileI->Component = storage;
 
 
    pkgTagFile TagFile(&File, File.Size());
    pkgTagFile TagFile(&File, File.Size());
@@ -902,19 +944,19 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
       return false;
       return false;
 
 
    std::string data;
    std::string data;
-   #define APT_INRELEASE(TAG, STORE) \
+   #define APT_INRELEASE(TYPE, TAG, STORE) \
    data = Section.FindS(TAG); \
    data = Section.FindS(TAG); \
    if (data.empty() == false) \
    if (data.empty() == false) \
    { \
    { \
-      map_ptrloc const storage = WriteUniqString(data); \
+      map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \
       STORE = storage; \
       STORE = storage; \
    }
    }
-   APT_INRELEASE("Suite", FileI->Archive)
-   APT_INRELEASE("Component", FileI->Component)
-   APT_INRELEASE("Version", FileI->Version)
-   APT_INRELEASE("Origin", FileI->Origin)
-   APT_INRELEASE("Codename", FileI->Codename)
-   APT_INRELEASE("Label", FileI->Label)
+   APT_INRELEASE(MIXED, "Suite", FileI->Archive)
+   APT_INRELEASE(MIXED, "Component", FileI->Component)
+   APT_INRELEASE(VERSIONNUMBER, "Version", FileI->Version)
+   APT_INRELEASE(MIXED, "Origin", FileI->Origin)
+   APT_INRELEASE(MIXED, "Codename", FileI->Codename)
+   APT_INRELEASE(MIXED, "Label", FileI->Label)
    #undef APT_INRELEASE
    #undef APT_INRELEASE
    Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic);
    Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic);
    Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades);
    Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades);

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

@@ -44,12 +44,11 @@ class debListParser : public pkgCacheGenerator::ListParser
    protected:
    protected:
    pkgTagFile Tags;
    pkgTagFile Tags;
    pkgTagSection Section;
    pkgTagSection Section;
-   unsigned long iOffset;
+   map_filesize_t iOffset;
    std::string Arch;
    std::string Arch;
    std::vector<std::string> Architectures;
    std::vector<std::string> Architectures;
    bool MultiArchEnabled;
    bool MultiArchEnabled;
 
 
-   unsigned long UniqFindTagWrite(const char *Tag);
    virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);
    virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);
    bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag,
    bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag,
 		     unsigned int Type);
 		     unsigned int Type);
@@ -77,8 +76,8 @@ class debListParser : public pkgCacheGenerator::ListParser
 #endif
 #endif
    virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
    virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
 			   pkgCache::VerIterator &Ver);
 			   pkgCache::VerIterator &Ver);
-   virtual unsigned long Offset() {return iOffset;};
-   virtual unsigned long Size() {return Section.size();};
+   virtual map_filesize_t Offset() {return iOffset;};
+   virtual map_filesize_t Size() {return Section.size();};
 
 
    virtual bool Step();
    virtual bool Step();
    
    

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

@@ -36,7 +36,7 @@ class debReleaseIndex : public metaIndex {
    /** \brief dpointer placeholder (for later in case we need it) */
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
    void *d;
    std::map<std::string, std::vector<debSectionEntry const*> > ArchEntries;
    std::map<std::string, std::vector<debSectionEntry const*> > ArchEntries;
-   enum { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted;
+   enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted;
 
 
    public:
    public:
 
 

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

@@ -239,7 +239,8 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
 /* */
 /* */
 debSrcRecordParser::~debSrcRecordParser()
 debSrcRecordParser::~debSrcRecordParser()
 {
 {
-   delete[] Buffer;
+   // was allocated via strndup()
+   free(Buffer);
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 

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

@@ -29,7 +29,7 @@ class debSystem : public pkgSystem
 {
 {
    // private d-pointer
    // private d-pointer
    debSystemPrivate *d;
    debSystemPrivate *d;
-   bool CheckUpdates();
+   APT_HIDDEN bool CheckUpdates();
 
 
    public:
    public:
 
 

+ 158 - 111
apt-pkg/deb/dpkgpm.cc

@@ -59,8 +59,8 @@ class pkgDPkgPMPrivate
 {
 {
 public:
 public:
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
-			term_out(NULL), history_out(NULL), 
-                        progress(NULL), master(-1), slave(-1)
+			term_out(NULL), history_out(NULL),
+                        progress(NULL), master(-1), slave(NULL)
    {
    {
       dpkgbuf[0] = '\0';
       dpkgbuf[0] = '\0';
    }
    }
@@ -77,9 +77,9 @@ public:
    APT::Progress::PackageManager *progress;
    APT::Progress::PackageManager *progress;
 
 
    // pty stuff
    // pty stuff
-   struct	termios tt;
+   struct termios tt;
    int master;
    int master;
-   int slave;
+   char * slave;
 
 
    // signals
    // signals
    sigset_t sigmask;
    sigset_t sigmask;
@@ -510,7 +510,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
    return result;
    return result;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// DPkgPM::DoStdin - Read stdin and pass to slave pty			/*{{{*/
+// DPkgPM::DoStdin - Read stdin and pass to master pty			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /*
 /*
 */
 */
@@ -564,8 +564,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
       'status:   <pkg>: <pkg  qstate>'
       'status:   <pkg>: <pkg  qstate>'
       'status:   <pkg>:<arch>: <pkg  qstate>'
       'status:   <pkg>:<arch>: <pkg  qstate>'
       
       
-      'processing: {install,configure,remove,purge,disappear,trigproc}: pkg'
-      'processing: {install,configure,remove,purge,disappear,trigproc}: trigger'
+      'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: pkg'
+      'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: trigger'
    */
    */
 
 
    // we need to split on ": " (note the appended space) as the ':' is
    // we need to split on ": " (note the appended space) as the ':' is
@@ -589,12 +589,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    std::string action;
    std::string action;
 
 
    // "processing" has the form "processing: action: pkg or trigger"
    // "processing" has the form "processing: action: pkg or trigger"
-   // with action = ["install", "configure", "remove", "purge", "disappear",
-   //                "trigproc"]
+   // with action = ["install", "upgrade", "configure", "remove", "purge",
+   //                "disappear", "trigproc"]
    if (prefix == "processing")
    if (prefix == "processing")
    {
    {
       pkgname = APT::String::Strip(list[2]);
       pkgname = APT::String::Strip(list[2]);
       action = APT::String::Strip(list[1]);
       action = APT::String::Strip(list[1]);
+      // we don't care for the difference (as dpkg doesn't really either)
+      if (action == "upgrade")
+	 action = "install";
    }
    }
    // "status" has the form: "status: pkg: state"
    // "status" has the form: "status: pkg: state"
    // with state in ["half-installed", "unpacked", "half-configured", 
    // with state in ["half-installed", "unpacked", "half-configured", 
@@ -621,15 +624,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    {
    {
       if(action == "error")
       if(action == "error")
       {
       {
-         d->progress->Error(list[1], PackagesDone, PackagesTotal,
+         d->progress->Error(pkgname, PackagesDone, PackagesTotal,
                             list[3]);
                             list[3]);
          pkgFailures++;
          pkgFailures++;
-         WriteApportReport(list[1].c_str(), list[3].c_str());
+         WriteApportReport(pkgname.c_str(), list[3].c_str());
          return;
          return;
       }
       }
       else if(action == "conffile-prompt")
       else if(action == "conffile-prompt")
       {
       {
-         d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal,
+         d->progress->ConffilePrompt(pkgname, PackagesDone, PackagesTotal,
                                      list[3]);
                                      list[3]);
          return;
          return;
       }
       }
@@ -638,27 +641,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    // at this point we know that we should have a valid pkgname, so build all 
    // at this point we know that we should have a valid pkgname, so build all 
    // the info from it
    // the info from it
 
 
-   // dpkg does not send always send "pkgname:arch" so we add it here 
-   // if needed
+   // dpkg does not always send "pkgname:arch" so we add it here if needed
    if (pkgname.find(":") == std::string::npos)
    if (pkgname.find(":") == std::string::npos)
    {
    {
-      // find the package in the group that is in a touched by dpkg
-      // if there are multiple dpkg will send us a full pkgname:arch
+      // find the package in the group that is touched by dpkg
+      // if there are multiple pkgs dpkg would send us a full pkgname:arch
       pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname);
       pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname);
-      if (Grp.end() == false) 
+      if (Grp.end() == false)
       {
       {
-          pkgCache::PkgIterator P = Grp.PackageList();
-          for (; P.end() != true; P = Grp.NextPkg(P))
-          {
-              if(Cache[P].Mode != pkgDepCache::ModeKeep)
-              {
-                  pkgname = P.FullName();
-                  break;
-              }
-          }
+	 pkgCache::PkgIterator P = Grp.PackageList();
+	 for (; P.end() != true; P = Grp.NextPkg(P))
+	 {
+	    if(Cache[P].Keep() == false || Cache[P].ReInstall() == true)
+	    {
+	       pkgname = P.FullName();
+	       break;
+	    }
+	 }
       }
       }
    }
    }
-   
+
    const char* const pkg = pkgname.c_str();
    const char* const pkg = pkgname.c_str();
    std::string short_pkgname = StringSplit(pkgname, ":")[0];
    std::string short_pkgname = StringSplit(pkgname, ":")[0];
    std::string arch = "";
    std::string arch = "";
@@ -697,28 +699,29 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    if (prefix == "status")
    if (prefix == "status")
    {
    {
       vector<struct DpkgState> const &states = PackageOps[pkg];
       vector<struct DpkgState> const &states = PackageOps[pkg];
-      const char *next_action = NULL;
       if(PackageOpsDone[pkg] < states.size())
       if(PackageOpsDone[pkg] < states.size())
-         next_action = states[PackageOpsDone[pkg]].state;
-      // check if the package moved to the next dpkg state
-      if(next_action && (action == next_action))
       {
       {
-         // only read the translation if there is actually a next
-         // action
-         const char *translation = _(states[PackageOpsDone[pkg]].str);
-         std::string msg;
-
-         // we moved from one dpkg state to a new one, report that
-         PackageOpsDone[pkg]++;
-         PackagesDone++;
-
-         strprintf(msg, translation, i18n_pkgname.c_str());
-         d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
-         
+         char const * const next_action = states[PackageOpsDone[pkg]].state;
+	 if (next_action && Debug == true)
+	    std::clog << "(parsed from dpkg) pkg: " << short_pkgname
+	       << " action: " << action << " (expected: '" << next_action << "' "
+	       << PackageOpsDone[pkg] << " of " << states.size() << ")" << endl;
+
+	 // check if the package moved to the next dpkg state
+	 if(next_action && (action == next_action))
+	 {
+	    // only read the translation if there is actually a next action
+	    char const * const translation = _(states[PackageOpsDone[pkg]].str);
+
+	    // we moved from one dpkg state to a new one, report that
+	    ++PackageOpsDone[pkg];
+	    ++PackagesDone;
+
+	    std::string msg;
+	    strprintf(msg, translation, i18n_pkgname.c_str());
+	    d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
+	 }
       }
       }
-      if (Debug == true) 
-         std::clog << "(parsed from dpkg) pkg: " << short_pkgname
-                   << " action: " << action << endl;
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1031,7 +1034,6 @@ void pkgDPkgPM::BuildPackagesProgressMap()
    }
    }
 }
 }
                                                                         /*}}}*/
                                                                         /*}}}*/
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13)
 bool pkgDPkgPM::Go(int StatusFd)
 bool pkgDPkgPM::Go(int StatusFd)
 {
 {
    APT::Progress::PackageManager *progress = NULL;
    APT::Progress::PackageManager *progress = NULL;
@@ -1040,68 +1042,134 @@ bool pkgDPkgPM::Go(int StatusFd)
    else
    else
       progress = new APT::Progress::PackageManagerProgressFd(StatusFd);
       progress = new APT::Progress::PackageManagerProgressFd(StatusFd);
    
    
-   return GoNoABIBreak(progress);
+   return Go(progress);
 }
 }
-#endif
 
 
 void pkgDPkgPM::StartPtyMagic()
 void pkgDPkgPM::StartPtyMagic()
 {
 {
    if (_config->FindB("Dpkg::Use-Pty", true) == false)
    if (_config->FindB("Dpkg::Use-Pty", true) == false)
    {
    {
-      d->master = d->slave = -1;
+      d->master = -1;
+      if (d->slave != NULL)
+	 free(d->slave);
+      d->slave = NULL;
       return;
       return;
    }
    }
 
 
-   // setup the pty and stuff
-   struct winsize win;
-
+   _error->PushToStack();
    // if tcgetattr for both stdin/stdout returns 0 (no error)
    // if tcgetattr for both stdin/stdout returns 0 (no error)
    // we do the pty magic
    // we do the pty magic
-   _error->PushToStack();
-   if (tcgetattr(STDIN_FILENO, &d->tt) == 0 &&
-       tcgetattr(STDOUT_FILENO, &d->tt) == 0)
+   if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 &&
+	 tcgetattr(STDIN_FILENO, &d->tt) == 0)
    {
    {
-       if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) < 0)
-       {
-           _error->Errno("ioctl", _("ioctl(TIOCGWINSZ) failed"));
-       } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0)
-       {
-           _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
-           d->master = d->slave = -1;
-        } else {
-	    struct termios rtt;
-	    rtt = d->tt;
-	    cfmakeraw(&rtt);
-	    rtt.c_lflag &= ~ECHO;
-	    rtt.c_lflag |= ISIG;
+      d->master = posix_openpt(O_RDWR | O_NOCTTY);
+      if (d->master == -1)
+	 _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+      else if (unlockpt(d->master) == -1)
+      {
+	 _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master);
+	 close(d->master);
+	 d->master = -1;
+      }
+      else
+      {
+	 char const * const slave_name = ptsname(d->master);
+	 if (slave_name == NULL)
+	 {
+	    _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master);
+	    close(d->master);
+	    d->master = -1;
+	 }
+	 else
+	 {
+	    d->slave = strdup(slave_name);
+	    if (d->slave == NULL)
+	    {
+	       _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master);
+	       close(d->master);
+	       d->master = -1;
+	    }
+	    struct winsize win;
+	    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0)
+	       _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!");
+	    if (ioctl(d->master, TIOCSWINSZ, &win) < 0)
+	       _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master);
+	    if (tcsetattr(d->master, TCSANOW, &d->tt) == -1)
+	       _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master);
+
+	    struct termios raw_tt;
+	    raw_tt = d->tt;
+	    cfmakeraw(&raw_tt);
+	    raw_tt.c_lflag &= ~ECHO;
+	    raw_tt.c_lflag |= ISIG;
 	    // block SIGTTOU during tcsetattr to prevent a hang if
 	    // block SIGTTOU during tcsetattr to prevent a hang if
 	    // the process is a member of the background process group
 	    // the process is a member of the background process group
 	    // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
 	    // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
 	    sigemptyset(&d->sigmask);
 	    sigemptyset(&d->sigmask);
 	    sigaddset(&d->sigmask, SIGTTOU);
 	    sigaddset(&d->sigmask, SIGTTOU);
 	    sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
 	    sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
-	    tcsetattr(0, TCSAFLUSH, &rtt);
-	    sigprocmask(SIG_SETMASK, &d->original_sigmask, 0);
-        }
+	    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1)
+	       _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!");
+	    sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL);
+	 }
       }
       }
-   // complain only if stdout is either a terminal (but still failed) or is an invalid
+   }
+   else
+   {
+      // complain only if stdout is either a terminal (but still failed) or is an invalid
       // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
       // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
-      else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
-         _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+      if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
+	 _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+   }
 
 
-      if (_error->PendingError() == true)
-	 _error->DumpErrors(std::cerr);
-      _error->RevertToStack();
+   if (_error->PendingError() == true)
+   {
+      if (d->master != -1)
+      {
+	 close(d->master);
+	 d->master = -1;
+      }
+      _error->DumpErrors(std::cerr);
+   }
+   _error->RevertToStack();
 }
 }
+void pkgDPkgPM::SetupSlavePtyMagic()
+{
+   if(d->master == -1)
+      return;
+
+   if (close(d->master) == -1)
+      _error->FatalE("close", "Closing master %d in child failed!", d->master);
+   if (setsid() == -1)
+      _error->FatalE("setsid", "Starting a new session for child failed!");
+
+   int const slaveFd = open(d->slave, O_RDWR);
+   if (slaveFd == -1)
+      _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+
+   if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)
+      _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd);
+   else
+   {
+      for (unsigned short i = 0; i < 3; ++i)
+	 if (dup2(slaveFd, i) == -1)
+	    _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i);
 
 
+      if (tcsetattr(0, TCSANOW, &d->tt) < 0)
+	 _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd);
+   }
+}
 void pkgDPkgPM::StopPtyMagic()
 void pkgDPkgPM::StopPtyMagic()
 {
 {
-   if(d->slave > 0)
-      close(d->slave);
+   if (d->slave != NULL)
+      free(d->slave);
+   d->slave = NULL;
    if(d->master >= 0) 
    if(d->master >= 0) 
    {
    {
-      tcsetattr(0, TCSAFLUSH, &d->tt);
+      if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1)
+	 _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!");
       close(d->master);
       close(d->master);
+      d->master = -1;
    }
    }
 }
 }
 
 
@@ -1114,11 +1182,7 @@ void pkgDPkgPM::StopPtyMagic()
  * through to human readable (and i10n-able)
  * through to human readable (and i10n-able)
  * names and calculates a percentage for each step.
  * names and calculates a percentage for each step.
  */
  */
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
 bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
 bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
-#else
-bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress)
-#endif
 {
 {
    pkgPackageManager::SigINTStop = false;
    pkgPackageManager::SigINTStop = false;
    d->progress = progress;
    d->progress = progress;
@@ -1413,22 +1477,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress)
       pid_t Child = ExecFork(KeepFDs);
       pid_t Child = ExecFork(KeepFDs);
       if (Child == 0)
       if (Child == 0)
       {
       {
-         // This is the child
-	 if(d->slave >= 0 && d->master >= 0) 
-	 {
-	    setsid();
-	    int res = ioctl(d->slave, TIOCSCTTY, 0);
-            if (res < 0) {
-               std::cerr << "ioctl(TIOCSCTTY) failed for fd: " 
-                         << d->slave << std::endl;
-            } else {
-               close(d->master);
-               dup2(d->slave, 0);
-               dup2(d->slave, 1);
-               dup2(d->slave, 2);
-               close(d->slave);
-            }
-	 }
+	 // This is the child
+	 SetupSlavePtyMagic();
 	 close(fd[0]); // close the read end of the pipe
 	 close(fd[0]); // close the read end of the pipe
 
 
 	 dpkgChrootDirectory();
 	 dpkgChrootDirectory();
@@ -1438,7 +1488,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress)
 
 
 	 if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
 	 if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
 	 {
 	 {
-	    int Flags,dummy;
+	    int Flags;
+            int dummy = 0;
 	    if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
 	    if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
 	       _exit(100);
 	       _exit(100);
 	    
 	    
@@ -1667,9 +1718,10 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
    // do not report dpkg I/O errors, this is a format string, so we compare
    // do not report dpkg I/O errors, this is a format string, so we compare
    // the prefix and the suffix of the error with the dpkg error message
    // the prefix and the suffix of the error with the dpkg error message
    vector<string> io_errors;
    vector<string> io_errors;
-   io_errors.push_back(string("failed to read on buffer copy for %s"));
-   io_errors.push_back(string("failed in write on buffer copy for %s"));
-   io_errors.push_back(string("short read on buffer copy for %s"));
+   io_errors.push_back(string("failed to read"));
+   io_errors.push_back(string("failed to write"));
+   io_errors.push_back(string("failed to seek"));
+   io_errors.push_back(string("unexpected end of file or stream"));
 
 
    for (vector<string>::iterator I = io_errors.begin(); I != io_errors.end(); ++I)
    for (vector<string>::iterator I = io_errors.begin(); I != io_errors.end(); ++I)
    {
    {
@@ -1702,11 +1754,6 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
    if (Ver.end() == true)
    if (Ver.end() == true)
       return;
       return;
    pkgver = Ver.VerStr() == NULL ? "unknown" : Ver.VerStr();
    pkgver = Ver.VerStr() == NULL ? "unknown" : Ver.VerStr();
-   pkgRecords Recs(Cache);
-   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
-   srcpkgname = Parse.SourcePkg();
-   if(srcpkgname.empty())
-      srcpkgname = pkgname;
 
 
    // if the file exists already, we check:
    // if the file exists already, we check:
    // - if it was reported already (touched by apport). 
    // - if it was reported already (touched by apport). 
@@ -1757,7 +1804,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
    time_t now = time(NULL);
    time_t now = time(NULL);
    fprintf(report, "Date: %s" , ctime(&now));
    fprintf(report, "Date: %s" , ctime(&now));
    fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str());
    fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str());
-   fprintf(report, "SourcePackage: %s\n", srcpkgname.c_str());
+   fprintf(report, "SourcePackage: %s\n", Ver.SourcePkgName());
    fprintf(report, "ErrorMessage:\n %s\n", errormsg);
    fprintf(report, "ErrorMessage:\n %s\n", errormsg);
 
 
    // ensure that the log is flushed
    // ensure that the log is flushed

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

@@ -52,7 +52,7 @@ class pkgDPkgPM : public pkgPackageManager
       needs to declare a Replaces on the disappeared package.
       needs to declare a Replaces on the disappeared package.
       \param pkgname Name of the package that disappeared
       \param pkgname Name of the package that disappeared
    */
    */
-   void handleDisappearAction(std::string const &pkgname);
+   APT_HIDDEN void handleDisappearAction(std::string const &pkgname);
 
 
    protected:
    protected:
    int pkgFailures;
    int pkgFailures;
@@ -110,6 +110,7 @@ class pkgDPkgPM : public pkgPackageManager
    // helper
    // helper
    void BuildPackagesProgressMap();
    void BuildPackagesProgressMap();
    void StartPtyMagic();
    void StartPtyMagic();
+   void SetupSlavePtyMagic();
    void StopPtyMagic();
    void StopPtyMagic();
    
    
    // input processing
    // input processing
@@ -117,27 +118,14 @@ class pkgDPkgPM : public pkgPackageManager
    void DoTerminalPty(int master);
    void DoTerminalPty(int master);
    void DoDpkgStatusFd(int statusfd);
    void DoDpkgStatusFd(int statusfd);
    void ProcessDpkgStatusLine(char *line);
    void ProcessDpkgStatusLine(char *line);
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13)
-   void DoDpkgStatusFd(int statusfd, int /*unused*/) {
-      DoDpkgStatusFd(statusfd);
-   }
-   void ProcessDpkgStatusLine(int /*unused*/, char *line) {
-      ProcessDpkgStatusLine(line);
-   }
-#endif
-
 
 
    // The Actuall installation implementation
    // The Actuall installation implementation
    virtual bool Install(PkgIterator Pkg,std::string File);
    virtual bool Install(PkgIterator Pkg,std::string File);
    virtual bool Configure(PkgIterator Pkg);
    virtual bool Configure(PkgIterator Pkg);
    virtual bool Remove(PkgIterator Pkg,bool Purge = false);
    virtual bool Remove(PkgIterator Pkg,bool Purge = false);
 
 
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
    virtual bool Go(APT::Progress::PackageManager *progress);
    virtual bool Go(APT::Progress::PackageManager *progress);
-#else
    virtual bool Go(int StatusFd=-1);
    virtual bool Go(int StatusFd=-1);
-   bool GoNoABIBreak(APT::Progress::PackageManager *progress);
-#endif
 
 
    virtual void Reset();
    virtual void Reset();
    
    

+ 19 - 4
apt-pkg/depcache.cc

@@ -663,10 +663,11 @@ void pkgDepCache::Update(OpProgress *Prog)
 {   
 {   
    iUsrSize = 0;
    iUsrSize = 0;
    iDownloadSize = 0;
    iDownloadSize = 0;
-   iDelCount = 0;
    iInstCount = 0;
    iInstCount = 0;
+   iDelCount = 0;
    iKeepCount = 0;
    iKeepCount = 0;
    iBrokenCount = 0;
    iBrokenCount = 0;
+   iPolicyBrokenCount = 0;
    iBadCount = 0;
    iBadCount = 0;
 
 
    // Perform the depends pass
    // Perform the depends pass
@@ -1225,7 +1226,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	       continue;
 	       continue;
 	    }
 	    }
 	    // now check if we should consider it a automatic dependency or not
 	    // now check if we should consider it a automatic dependency or not
-	    if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
+	    if(InstPkg->CurrentVer == 0 && InstVer->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", InstVer.Section()))
 	    {
 	    {
 	       if(DebugAutoInstall == true)
 	       if(DebugAutoInstall == true)
 		  std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct "
 		  std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct "
@@ -1374,7 +1375,7 @@ bool pkgDepCache::IsInstallOkDependenciesSatisfiableByCandidates(PkgIterator con
 
 
 	 // the dependency is critical, but can't be installed, so discard the candidate
 	 // the dependency is critical, but can't be installed, so discard the candidate
 	 // as the problemresolver will trip over it otherwise trying to install it (#735967)
 	 // as the problemresolver will trip over it otherwise trying to install it (#735967)
-	 if (Pkg->CurrentVer != 0)
+	 if (Pkg->CurrentVer != 0 && (PkgState[Pkg->ID].iFlags & Protected) != Protected)
 	    SetCandidateVersion(Pkg.CurrentVer());
 	    SetCandidateVersion(Pkg.CurrentVer());
 	 return false;
 	 return false;
       }
       }
@@ -1678,7 +1679,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk
 {
 {
    /* Not source/not automatic versions cannot be a candidate version 
    /* Not source/not automatic versions cannot be a candidate version 
       unless they are already installed */
       unless they are already installed */
-   VerIterator Last(*(pkgCache *)this,0);
+   VerIterator Last;
    
    
    for (VerIterator I = Pkg.VersionList(); I.end() == false; ++I)
    for (VerIterator I = Pkg.VersionList(); I.end() == false; ++I)
    {
    {
@@ -1960,3 +1961,17 @@ bool pkgDepCache::Sweep()						/*{{{*/
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// DepCache::MarkAndSweep						/*{{{*/
+bool pkgDepCache::MarkAndSweep(InRootSetFunc &rootFunc)
+{
+   return MarkRequired(rootFunc) && Sweep();
+}
+bool pkgDepCache::MarkAndSweep()
+{
+   std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
+   if(f.get() != NULL)
+      return MarkAndSweep(*f.get());
+   else
+      return false;
+}
+									/*}}}*/

+ 7 - 18
apt-pkg/depcache.h

@@ -91,7 +91,7 @@ class pkgDepCache : protected pkgCache::Namespace
     *  \param follow_suggests If \b true, suggestions of the package
     *  \param follow_suggests If \b true, suggestions of the package
     *  will be recursively marked.
     *  will be recursively marked.
     */
     */
-   void MarkPackage(const pkgCache::PkgIterator &pkg,
+   APT_HIDDEN void MarkPackage(const pkgCache::PkgIterator &pkg,
 		    const pkgCache::VerIterator &ver,
 		    const pkgCache::VerIterator &ver,
 		    bool const &follow_recommends,
 		    bool const &follow_recommends,
 		    bool const &follow_suggests);
 		    bool const &follow_suggests);
@@ -109,7 +109,7 @@ class pkgDepCache : protected pkgCache::Namespace
     *
     *
     *  \return \b false if an error occurred.
     *  \return \b false if an error occurred.
     */
     */
-   bool MarkRequired(InRootSetFunc &rootFunc);
+   APT_HIDDEN bool MarkRequired(InRootSetFunc &rootFunc);
 
 
    /** \brief Set the StateCache::Garbage flag on all packages that
    /** \brief Set the StateCache::Garbage flag on all packages that
     *  should be removed.
     *  should be removed.
@@ -120,7 +120,7 @@ class pkgDepCache : protected pkgCache::Namespace
     *
     *
     *  \return \b false if an error occurred.
     *  \return \b false if an error occurred.
     */
     */
-   bool Sweep();
+   APT_HIDDEN bool Sweep();
 
 
    public:
    public:
    
    
@@ -169,7 +169,7 @@ class pkgDepCache : protected pkgCache::Namespace
        bool released;
        bool released;
 
 
        /** Action groups are noncopyable. */
        /** Action groups are noncopyable. */
-       ActionGroup(const ActionGroup &other);
+       APT_HIDDEN ActionGroup(const ActionGroup &other);
    public:
    public:
        /** \brief Create a new ActionGroup.
        /** \brief Create a new ActionGroup.
 	*
 	*
@@ -396,19 +396,8 @@ class pkgDepCache : protected pkgCache::Namespace
     *  \param rootFunc A predicate that returns \b true for packages
     *  \param rootFunc A predicate that returns \b true for packages
     *  that should be added to the root set.
     *  that should be added to the root set.
     */
     */
-   bool MarkAndSweep(InRootSetFunc &rootFunc)
-   {
-     return MarkRequired(rootFunc) && Sweep();
-   }
-
-   bool MarkAndSweep()
-   {
-     std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
-     if(f.get() != NULL)
-       return MarkAndSweep(*f.get());
-     else
-       return false;
-   }
+   bool MarkAndSweep(InRootSetFunc &rootFunc);
+   bool MarkAndSweep();
 
 
    /** \name State Manipulators
    /** \name State Manipulators
     */
     */
@@ -514,7 +503,7 @@ class pkgDepCache : protected pkgCache::Namespace
 	 bool const rPurge, unsigned long const Depth, bool const FromUser);
 	 bool const rPurge, unsigned long const Depth, bool const FromUser);
 
 
    private:
    private:
-   bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
+   APT_HIDDEN bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
 			unsigned long const Depth, bool const FromUser);
 			unsigned long const Depth, bool const FromUser);
 };
 };
 
 

+ 62 - 10
apt-pkg/edsp.cc

@@ -18,6 +18,7 @@
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/pkgrecords.h>
 
 
 #include <ctype.h>
 #include <ctype.h>
 #include <stddef.h>
 #include <stddef.h>
@@ -25,6 +26,7 @@
 #include <time.h>
 #include <time.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <algorithm>
 #include <iostream>
 #include <iostream>
 #include <vector>
 #include <vector>
 #include <limits>
 #include <limits>
@@ -49,7 +51,12 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
    if (Progress != NULL)
    if (Progress != NULL)
       Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
       Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
    unsigned long p = 0;
    unsigned long p = 0;
+   std::vector<std::string> archs = APT::Configuration::getArchitectures();
    for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
    for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+   {
+      std::string const arch = Pkg.Arch();
+      if (std::find(archs.begin(), archs.end(), arch) == archs.end())
+	 continue;
       for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p)
       for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p)
       {
       {
 	 WriteScenarioVersion(Cache, output, Pkg, Ver);
 	 WriteScenarioVersion(Cache, output, Pkg, Ver);
@@ -58,6 +65,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
 	 if (Progress != NULL && p % 100 == 0)
 	 if (Progress != NULL && p % 100 == 0)
 	    Progress->Progress(p);
 	    Progress->Progress(p);
       }
       }
+   }
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -88,6 +96,7 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI
 				pkgCache::VerIterator const &Ver)
 				pkgCache::VerIterator const &Ver)
 {
 {
    fprintf(output, "Package: %s\n", Pkg.Name());
    fprintf(output, "Package: %s\n", Pkg.Name());
+   fprintf(output, "Source: %s\n", Ver.SourcePkgName());
    fprintf(output, "Architecture: %s\n", Ver.Arch());
    fprintf(output, "Architecture: %s\n", Ver.Arch());
    fprintf(output, "Version: %s\n", Ver.VerStr());
    fprintf(output, "Version: %s\n", Ver.VerStr());
    if (Pkg.CurrentVer() == Ver)
    if (Pkg.CurrentVer() == Ver)
@@ -107,10 +116,22 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI
    else if ((Ver->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
    else if ((Ver->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
       fprintf(output, "Multi-Arch: same\n");
       fprintf(output, "Multi-Arch: same\n");
    signed short Pin = std::numeric_limits<signed short>::min();
    signed short Pin = std::numeric_limits<signed short>::min();
-   for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) {
-      signed short const p = Cache.GetPolicy().GetPriority(File.File());
+   std::set<string> Releases;
+   for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; ++I) {
+      pkgCache::PkgFileIterator File = I.File();
+      signed short const p = Cache.GetPolicy().GetPriority(File);
       if (Pin < p)
       if (Pin < p)
 	 Pin = p;
 	 Pin = p;
+      if ((File->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) {
+	 string Release = File.RelStr();
+	 if (!Release.empty())
+	    Releases.insert(Release);
+      }
+   }
+   if (!Releases.empty()) {
+       fprintf(output, "APT-Release:\n");
+       for (std::set<string>::iterator R = Releases.begin(); R != Releases.end(); ++R)
+	   fprintf(output, " %s\n", R->c_str());
    }
    }
    fprintf(output, "APT-Pin: %d\n", Pin);
    fprintf(output, "APT-Pin: %d\n", Pin);
    if (Cache.GetCandidateVer(Pkg) == Ver)
    if (Cache.GetCandidateVer(Pkg) == Ver)
@@ -231,7 +252,16 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
 	 continue;
 	 continue;
       req->append(" ").append(Pkg.FullName());
       req->append(" ").append(Pkg.FullName());
    }
    }
-   fprintf(output, "Request: EDSP 0.4\n");
+   fprintf(output, "Request: EDSP 0.5\n");
+
+   const char *arch = _config->Find("APT::Architecture").c_str();
+   std::vector<string> archs = APT::Configuration::getArchitectures();
+   fprintf(output, "Architecture: %s\n", arch);
+   fprintf(output, "Architectures:");
+   for (std::vector<string>::const_iterator a = archs.begin(); a != archs.end(); ++a)
+       fprintf(output, " %s", a->c_str());
+   fprintf(output, "\n");
+
    if (del.empty() == false)
    if (del.empty() == false)
       fprintf(output, "Remove: %s\n", del.c_str()+1);
       fprintf(output, "Remove: %s\n", del.c_str()+1);
    if (inst.empty() == false)
    if (inst.empty() == false)
@@ -411,6 +441,13 @@ bool EDSP::ReadRequest(int const input, std::list<std::string> &install,
 	    distUpgrade = EDSP::StringToBool(line.c_str() + 14, false);
 	    distUpgrade = EDSP::StringToBool(line.c_str() + 14, false);
 	 else if (line.compare(0, 11, "Autoremove:") == 0)
 	 else if (line.compare(0, 11, "Autoremove:") == 0)
 	    autoRemove = EDSP::StringToBool(line.c_str() + 12, false);
 	    autoRemove = EDSP::StringToBool(line.c_str() + 12, false);
+	 else if (line.compare(0, 13, "Architecture:") == 0)
+	    _config->Set("APT::Architecture", line.c_str() + 14);
+	 else if (line.compare(0, 14, "Architectures:") == 0)
+	 {
+	    std::string const archs = line.c_str() + 15;
+	    _config->Set("APT::Architectures", SubstVar(archs, " ", ","));
+	 }
 	 else
 	 else
 	    _error->Warning("Unknown line in EDSP Request stanza: %s", line.c_str());
 	    _error->Warning("Unknown line in EDSP Request stanza: %s", line.c_str());
 
 
@@ -508,7 +545,7 @@ bool EDSP::WriteError(char const * const uuid, std::string const &message, FILE*
 }
 }
 									/*}}}*/
 									/*}}}*/
 // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes	{{{*/
 // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes	{{{*/
-bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) {
+pid_t EDSP::ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool) {
 	std::vector<std::string> const solverDirs = _config->FindVector("Dir::Bin::Solvers");
 	std::vector<std::string> const solverDirs = _config->FindVector("Dir::Bin::Solvers");
 	std::string file;
 	std::string file;
 	for (std::vector<std::string>::const_iterator dir = solverDirs.begin();
 	for (std::vector<std::string>::const_iterator dir = solverDirs.begin();
@@ -520,10 +557,16 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o
 	}
 	}
 
 
 	if (file.empty() == true)
 	if (file.empty() == true)
-		return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver);
+	{
+		_error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver);
+		return 0;
+	}
 	int external[4] = {-1, -1, -1, -1};
 	int external[4] = {-1, -1, -1, -1};
 	if (pipe(external) != 0 || pipe(external + 2) != 0)
 	if (pipe(external) != 0 || pipe(external + 2) != 0)
-		return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP");
+	{
+		_error->Errno("Resolve", "Can't create needed IPC pipes for EDSP");
+		return 0;
+	}
 	for (int i = 0; i < 4; ++i)
 	for (int i = 0; i < 4; ++i)
 		SetCloseExec(external[i], true);
 		SetCloseExec(external[i], true);
 
 
@@ -540,11 +583,19 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o
 	close(external[3]);
 	close(external[3]);
 
 
 	if (WaitFd(external[1], true, 5) == false)
 	if (WaitFd(external[1], true, 5) == false)
-		return _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin");
+	{
+		_error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin");
+		return 0;
+	}
 
 
 	*solver_in = external[1];
 	*solver_in = external[1];
 	*solver_out = external[2];
 	*solver_out = external[2];
-	return true;
+	return Solver;
+}
+bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) {
+   if (ExecuteSolver(solver, solver_in, solver_out, true) == 0)
+      return false;
+   return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // EDSP::ResolveExternal - resolve problems by asking external for help	{{{*/
 // EDSP::ResolveExternal - resolve problems by asking external for help	{{{*/
@@ -552,7 +603,8 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
 			 bool const upgrade, bool const distUpgrade,
 			 bool const upgrade, bool const distUpgrade,
 			 bool const autoRemove, OpProgress *Progress) {
 			 bool const autoRemove, OpProgress *Progress) {
 	int solver_in, solver_out;
 	int solver_in, solver_out;
-	if (EDSP::ExecuteSolver(solver, &solver_in, &solver_out) == false)
+	pid_t const solver_pid = EDSP::ExecuteSolver(solver, &solver_in, &solver_out, true);
+	if (solver_pid == 0)
 		return false;
 		return false;
 
 
 	FILE* output = fdopen(solver_in, "w");
 	FILE* output = fdopen(solver_in, "w");
@@ -572,6 +624,6 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
 	if (EDSP::ReadResponse(solver_out, Cache, Progress) == false)
 	if (EDSP::ReadResponse(solver_out, Cache, Progress) == false)
 		return false;
 		return false;
 
 
-	return true;
+	return ExecWait(solver_pid, solver);
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 3 - 3
apt-pkg/edsp.h

@@ -205,10 +205,10 @@ public:
 	 *  \param[out] solver_in will be the stdin of the solver
 	 *  \param[out] solver_in will be the stdin of the solver
 	 *  \param[out] solver_out will be the stdout of the solver
 	 *  \param[out] solver_out will be the stdout of the solver
 	 *
 	 *
-	 *  \return true if the solver could be started and the pipes
-	 *  are set up correctly, otherwise false and the pipes are invalid
+	 *  \return PID of the started solver or 0 if failure occurred
 	 */
 	 */
-	bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out);
+	pid_t static ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/);
+	APT_DEPRECATED bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out);
 
 
 	/** \brief call an external resolver to handle the request
 	/** \brief call an external resolver to handle the request
 	 *
 	 *

+ 1 - 1
apt-pkg/edsp/edspindexfile.cc

@@ -56,7 +56,7 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
    CFile->Size = Pkg.FileSize();
    CFile->Size = Pkg.FileSize();
    CFile->mtime = Pkg.ModificationTime();
    CFile->mtime = Pkg.ModificationTime();
-   map_ptrloc const storage = Gen.WriteUniqString("edsp::scenario");
+   map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "edsp::scenario");
    CFile->Archive = storage;
    CFile->Archive = storage;
 
 
    if (Gen.MergeList(Parser) == false)
    if (Gen.MergeList(Parser) == false)

+ 2 - 2
apt-pkg/indexcopy.h

@@ -93,8 +93,8 @@ class SigVerify								/*{{{*/
    /** \brief dpointer placeholder (for later in case we need it) */
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
    void *d;
 
 
-   bool Verify(std::string prefix,std::string file, indexRecords *records);
-   bool CopyMetaIndex(std::string CDROM, std::string CDName, 
+   APT_HIDDEN bool Verify(std::string prefix,std::string file, indexRecords *records);
+   APT_HIDDEN bool CopyMetaIndex(std::string CDROM, std::string CDName,
 		      std::string prefix, std::string file);
 		      std::string prefix, std::string file);
 
 
  public:
  public:

+ 29 - 10
apt-pkg/indexrecords.cc

@@ -37,6 +37,11 @@ APT_PURE string indexRecords::GetSuite() const
    return this->Suite;
    return this->Suite;
 }
 }
 
 
+APT_PURE bool indexRecords::GetSupportsAcquireByHash() const
+{
+   return this->SupportsAcquireByHash;
+}
+
 APT_PURE bool indexRecords::CheckDist(const string MaybeDist) const
 APT_PURE bool indexRecords::CheckDist(const string MaybeDist) const
 {
 {
    return (this->Dist == MaybeDist
    return (this->Dist == MaybeDist
@@ -86,12 +91,14 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
       strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
       strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
       return false;
       return false;
    }
    }
+   // FIXME: find better tag name
+   SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false);
 
 
    Suite = Section.FindS("Suite");
    Suite = Section.FindS("Suite");
    Dist = Section.FindS("Codename");
    Dist = Section.FindS("Codename");
 
 
-   int i;
-   for (i=0;HashString::SupportedHashes()[i] != NULL; i++)
+   bool FoundHashSum = false;
+   for (int i=0;HashString::SupportedHashes()[i] != NULL; i++)
    {
    {
       if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
       if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
 	 continue;
 	 continue;
@@ -103,16 +110,28 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
       {
       {
 	 if (!parseSumData(Start, End, Name, Hash, Size))
 	 if (!parseSumData(Start, End, Name, Hash, Size))
 	    return false;
 	    return false;
-	 indexRecords::checkSum *Sum = new indexRecords::checkSum;
-	 Sum->MetaKeyFilename = Name;
-	 Sum->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
-	 Sum->Size = Size;
-	 Entries[Name] = Sum;
+
+         if (Entries.find(Name) == Entries.end())
+         {
+            indexRecords::checkSum *Sum = new indexRecords::checkSum;
+            Sum->MetaKeyFilename = Name;
+            Sum->Size = Size;
+#if __GNUC__ >= 4
+       #pragma GCC diagnostic push
+       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+            Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);
+#if __GNUC__ >= 4
+       #pragma GCC diagnostic pop
+#endif
+            Entries[Name] = Sum;
+         }
+         Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
+         FoundHashSum = true;
       }
       }
-      break;
    }
    }
 
 
-   if(HashString::SupportedHashes()[i] == NULL)
+   if(FoundHashSum == false)
    {
    {
       strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
       strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
       return false;
       return false;
@@ -239,6 +258,6 @@ indexRecords::indexRecords()
 }
 }
 
 
 indexRecords::indexRecords(const string ExpectedDist) :
 indexRecords::indexRecords(const string ExpectedDist) :
-   ExpectedDist(ExpectedDist), ValidUntil(0)
+   ExpectedDist(ExpectedDist), ValidUntil(0), SupportsAcquireByHash(false)
 {
 {
 }
 }

+ 5 - 1
apt-pkg/indexrecords.h

@@ -21,17 +21,20 @@
 
 
 class indexRecords
 class indexRecords
 {
 {
-   bool parseSumData(const char *&Start, const char *End, std::string &Name,
+   APT_HIDDEN bool parseSumData(const char *&Start, const char *End, std::string &Name,
 		     std::string &Hash, unsigned long long &Size);
 		     std::string &Hash, unsigned long long &Size);
    public:
    public:
    struct checkSum;
    struct checkSum;
    std::string ErrorText;
    std::string ErrorText;
+   // dpointer (for later9
+   void * d;
    
    
    protected:
    protected:
    std::string Dist;
    std::string Dist;
    std::string Suite;
    std::string Suite;
    std::string ExpectedDist;
    std::string ExpectedDist;
    time_t ValidUntil;
    time_t ValidUntil;
+   bool SupportsAcquireByHash;
 
 
    std::map<std::string,checkSum *> Entries;
    std::map<std::string,checkSum *> Entries;
 
 
@@ -49,6 +52,7 @@ class indexRecords
    virtual bool Load(std::string Filename);
    virtual bool Load(std::string Filename);
    std::string GetDist() const;
    std::string GetDist() const;
    std::string GetSuite() const;
    std::string GetSuite() const;
+   bool GetSupportsAcquireByHash() const;
    time_t GetValidUntil() const;
    time_t GetValidUntil() const;
    virtual bool CheckDist(const std::string MaybeDist) const;
    virtual bool CheckDist(const std::string MaybeDist) const;
    std::string GetExpectedDist() const;
    std::string GetExpectedDist() const;

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

@@ -21,6 +21,8 @@
 namespace APT {
 namespace APT {
 namespace Progress {
 namespace Progress {
 
 
+PackageManager::PackageManager() : d(NULL), percentage(0.0), last_reported_progress(-1) {}
+PackageManager::~PackageManager() {}
 
 
 /* Return a APT::Progress::PackageManager based on the global
 /* Return a APT::Progress::PackageManager based on the global
  * apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd)
  * apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd)

+ 3 - 4
apt-pkg/install-progress.h

@@ -26,9 +26,8 @@ namespace Progress {
     int last_reported_progress;
     int last_reported_progress;
 
 
  public:
  public:
-    PackageManager()
-       : percentage(0.0), last_reported_progress(-1) {};
-    virtual ~PackageManager() {};
+    PackageManager();
+    virtual ~PackageManager();
 
 
     /* Global Start/Stop */
     /* Global Start/Stop */
     virtual void Start(int /*child_pty*/=-1) {};
     virtual void Start(int /*child_pty*/=-1) {};
@@ -120,7 +119,7 @@ namespace Progress {
  class PackageManagerFancy : public PackageManager
  class PackageManagerFancy : public PackageManager
  {
  {
  private:
  private:
-    static void staticSIGWINCH(int);
+    APT_HIDDEN static void staticSIGWINCH(int);
     static std::vector<PackageManagerFancy*> instances;
     static std::vector<PackageManagerFancy*> instances;
     APT_HIDDEN bool DrawStatusLine();
     APT_HIDDEN bool DrawStatusLine();
 
 

+ 1 - 1
apt-pkg/metaindex.h

@@ -53,7 +53,7 @@ class metaIndex
 
 
    metaIndex(std::string const &URI, std::string const &Dist, 
    metaIndex(std::string const &URI, std::string const &Dist, 
              char const * const Type) 
              char const * const Type) 
-      : Indexes(NULL), Type(Type), URI(URI), Dist(Dist)
+      : Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false)
    {
    {
       /* nothing */
       /* nothing */
    }
    }

+ 49 - 2
apt-pkg/packagemanager.cc

@@ -373,6 +373,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
    std::list<DepIterator> needConfigure;
    std::list<DepIterator> needConfigure;
    do
    do
    {
    {
+      // Check each dependency and see if anything needs to be done
+      // so that it can be configured
       Changed = false;
       Changed = false;
       for (DepIterator D = instVer.DependsList(); D.end() == false; )
       for (DepIterator D = instVer.DependsList(); D.end() == false; )
       {
       {
@@ -384,7 +386,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	    continue;
 	    continue;
 	 Bad = true;
 	 Bad = true;
 
 
-	 // Check for dependencies that have not been unpacked, probably due to loops.
+         // the first pass checks if we its all good, i.e. if we have
+         // to do anything at all
 	 for (DepIterator Cur = Start; true; ++Cur)
 	 for (DepIterator Cur = Start; true; ++Cur)
 	 {
 	 {
 	    SPtrArray<Version *> VList = Cur.AllTargets();
 	    SPtrArray<Version *> VList = Cur.AllTargets();
@@ -403,6 +406,47 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 		  break;
 		  break;
 	       }
 	       }
 
 
+	       // Check if the version that is going to be installed will satisfy the dependency
+	       if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
+		  continue;
+
+	       if (PkgLoop == true)
+	       {
+		  if (Debug)
+		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
+	          Bad = false;
+	       }
+	    }
+
+            if (Cur == End || Bad == false)
+	       break;
+         }
+
+         // this dependency is in a good state, so we can stop
+         if (Bad == false)
+         {
+            if (Debug)
+               std::clog << OutputInDepth(Depth) << "Found ok dep " << D.TargetPkg() << std::endl;
+            continue;
+         }
+
+	 // Check for dependencies that have not been unpacked, 
+         // probably due to loops.
+	 for (DepIterator Cur = Start; true; ++Cur)
+	 {
+	    SPtrArray<Version *> VList = Cur.AllTargets();
+
+	    for (Version **I = VList; *I != 0; ++I)
+	    {
+	       VerIterator Ver(Cache,*I);
+	       PkgIterator DepPkg = Ver.ParentPkg();
+
+	       // Check if the current version of the package is available and will satisfy this dependency
+	       if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
+		   List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
+		   DepPkg.State() == PkgIterator::NeedsNothing)
+                  continue;
+
 	       // Check if the version that is going to be installed will satisfy the dependency
 	       // Check if the version that is going to be installed will satisfy the dependency
 	       if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
 	       if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
 		  continue;
 		  continue;
@@ -420,6 +464,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 		  if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
 		  if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
 		     return false;
 		     return false;
 	       }
 	       }
+               // at this point we either unpacked a Dep or we are in a loop,
+               // no need to unpack a second one
 	       break;
 	       break;
 	    }
 	    }
 
 
@@ -436,6 +482,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
          return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str());
          return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str());
    } while (Changed == true);
    } while (Changed == true);
 
 
+   // now go over anything that needs configuring
    Bad = false, Changed = false, i = 0;
    Bad = false, Changed = false, i = 0;
    do
    do
    {
    {
@@ -1033,7 +1080,7 @@ pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress)
       return Failed;
       return Failed;
    
    
    return Res;
    return Res;
-};
+}
 #else
 #else
 pkgPackageManager::OrderResult
 pkgPackageManager::OrderResult
 pkgPackageManager::DoInstallPostFork(int statusFd)
 pkgPackageManager::DoInstallPostFork(int statusFd)

+ 3 - 2
apt-pkg/packagemanager.h

@@ -47,8 +47,8 @@ class pkgRecords;
 namespace APT {
 namespace APT {
    namespace Progress {
    namespace Progress {
       class PackageManager;
       class PackageManager;
-   };
-};
+   }
+}
 
 
 
 
 class pkgPackageManager : protected pkgCache::Namespace
 class pkgPackageManager : protected pkgCache::Namespace
@@ -98,6 +98,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
    virtual bool Go(APT::Progress::PackageManager * /*progress*/) {return true;};
    virtual bool Go(APT::Progress::PackageManager * /*progress*/) {return true;};
+   virtual bool Go(int /*statusFd*/=-1) {return true;};
 #else
 #else
    virtual bool Go(int /*statusFd*/=-1) {return true;};
    virtual bool Go(int /*statusFd*/=-1) {return true;};
 #endif
 #endif

+ 34 - 41
apt-pkg/pkgcache.cc

@@ -54,12 +54,8 @@ pkgCache::Header::Header()
    
    
    /* Whenever the structures change the major version should be bumped,
    /* Whenever the structures change the major version should be bumped,
       whenever the generator changes the minor version should be bumped. */
       whenever the generator changes the minor version should be bumped. */
-   MajorVersion = 9;
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-   MinorVersion = 2;
-#else
-   MinorVersion = 1;
-#endif
+   MajorVersion = 10;
+   MinorVersion = 0;
    Dirty = false;
    Dirty = false;
    
    
    HeaderSz = sizeof(pkgCache::Header);
    HeaderSz = sizeof(pkgCache::Header);
@@ -86,11 +82,10 @@ pkgCache::Header::Header()
    MaxDescFileSize = 0;
    MaxDescFileSize = 0;
    
    
    FileList = 0;
    FileList = 0;
-   StringList = 0;
    VerSysName = 0;
    VerSysName = 0;
    Architecture = 0;
    Architecture = 0;
-   memset(PkgHashTable,0,sizeof(PkgHashTable));
-   memset(GrpHashTable,0,sizeof(GrpHashTable));
+   Architectures = 0;
+   HashTableSize = _config->FindI("APT::Cache-HashTableSize", 10 * 1048);
    memset(Pools,0,sizeof(Pools));
    memset(Pools,0,sizeof(Pools));
 
 
    CacheFileSize = 0;
    CacheFileSize = 0;
@@ -145,7 +140,6 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    DescP = (Description *)Map.Data();
    DescP = (Description *)Map.Data();
    ProvideP = (Provides *)Map.Data();
    ProvideP = (Provides *)Map.Data();
    DepP = (Dependency *)Map.Data();
    DepP = (Dependency *)Map.Data();
-   StringItemP = (StringItem *)Map.Data();
    StrP = (char *)Map.Data();
    StrP = (char *)Map.Data();
 
 
    if (Errorchecks == false)
    if (Errorchecks == false)
@@ -193,20 +187,20 @@ bool pkgCache::ReMap(bool const &Errorchecks)
 /* This is used to generate the hash entries for the HashTable. With my
 /* This is used to generate the hash entries for the HashTable. With my
    package list from bo this function gets 94% table usage on a 512 item
    package list from bo this function gets 94% table usage on a 512 item
    table (480 used items) */
    table (480 used items) */
-unsigned long pkgCache::sHash(const string &Str) const
+map_id_t pkgCache::sHash(const string &Str) const
 {
 {
    unsigned long Hash = 0;
    unsigned long Hash = 0;
    for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
    for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
       Hash = 41 * Hash + tolower_ascii(*I);
       Hash = 41 * Hash + tolower_ascii(*I);
-   return Hash % _count(HeaderP->PkgHashTable);
+   return Hash % HeaderP->HashTableSize;
 }
 }
 
 
-unsigned long pkgCache::sHash(const char *Str) const
+map_id_t pkgCache::sHash(const char *Str) const
 {
 {
    unsigned long Hash = tolower_ascii(*Str);
    unsigned long Hash = tolower_ascii(*Str);
    for (const char *I = Str + 1; *I != 0; ++I)
    for (const char *I = Str + 1; *I != 0; ++I)
       Hash = 41 * Hash + tolower_ascii(*I);
       Hash = 41 * Hash + tolower_ascii(*I);
-   return Hash % _count(HeaderP->PkgHashTable);
+   return Hash % HeaderP->HashTableSize;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Cache::SingleArchFindPkg - Locate a package by name			/*{{{*/
 // Cache::SingleArchFindPkg - Locate a package by name			/*{{{*/
@@ -217,13 +211,10 @@ unsigned long pkgCache::sHash(const char *Str) const
 pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
 pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
 {
 {
    // Look at the hash bucket
    // Look at the hash bucket
-   Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)];
-   for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
+   Package *Pkg = PkgP + HeaderP->PkgHashTable()[Hash(Name)];
+   for (; Pkg != PkgP; Pkg = PkgP + Pkg->Next)
    {
    {
-      if (unlikely(Pkg->Name == 0))
-	 continue;
-
-      int const cmp = strcasecmp(Name.c_str(), StrP + Pkg->Name);
+      int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name);
       if (cmp == 0)
       if (cmp == 0)
 	 return PkgIterator(*this, Pkg);
 	 return PkgIterator(*this, Pkg);
       else if (cmp < 0)
       else if (cmp < 0)
@@ -282,12 +273,9 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
 		return GrpIterator(*this,0);
 		return GrpIterator(*this,0);
 
 
 	// Look at the hash bucket for the group
 	// Look at the hash bucket for the group
-	Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)];
+	Group *Grp = GrpP + HeaderP->GrpHashTable()[sHash(Name)];
 	for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
 	for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
-		if (unlikely(Grp->Name == 0))
-		   continue;
-
-		int const cmp = strcasecmp(Name.c_str(), StrP + Grp->Name);
+		int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
 		if (cmp == 0)
 		if (cmp == 0)
 			return GrpIterator(*this, Grp);
 			return GrpIterator(*this, Grp);
 		else if (cmp < 0)
 		else if (cmp < 0)
@@ -364,19 +352,15 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
 	   last one we check, so we do it now. */
 	   last one we check, so we do it now. */
 	if (Arch == "native" || Arch == myArch || Arch == "all") {
 	if (Arch == "native" || Arch == myArch || Arch == "all") {
 		pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
 		pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
-		if (strcasecmp(myArch, Owner->StrP + Pkg->Arch) == 0)
+		if (strcmp(myArch, Owner->StrP + Pkg->Arch) == 0)
 			return PkgIterator(*Owner, Pkg);
 			return PkgIterator(*Owner, Pkg);
 		Arch = myArch;
 		Arch = myArch;
 	}
 	}
 
 
-	/* Iterate over the list to find the matching arch
-	   unfortunately this list includes "package noise"
-	   (= different packages with same calculated hash),
-	   so we need to check the name also */
+	// Iterate over the list to find the matching arch
 	for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
 	for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
-	     Pkg = Owner->PkgP + Pkg->NextPackage) {
-		if (S->Name == Pkg->Name &&
-		    stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0)
+	     Pkg = Owner->PkgP + Pkg->Next) {
+		if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0)
 			return PkgIterator(*Owner, Pkg);
 			return PkgIterator(*Owner, Pkg);
 		if ((Owner->PkgP + S->LastPackage) == Pkg)
 		if ((Owner->PkgP + S->LastPackage) == Pkg)
 			break;
 			break;
@@ -423,7 +407,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const
 	if (S->LastPackage == LastPkg.Index())
 	if (S->LastPackage == LastPkg.Index())
 		return PkgIterator(*Owner, 0);
 		return PkgIterator(*Owner, 0);
 
 
-	return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage);
+	return PkgIterator(*Owner, Owner->PkgP + LastPkg->Next);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // GrpIterator::operator ++ - Postfix incr				/*{{{*/
 // GrpIterator::operator ++ - Postfix incr				/*{{{*/
@@ -436,10 +420,10 @@ void pkgCache::GrpIterator::operator ++(int)
       S = Owner->GrpP + S->Next;
       S = Owner->GrpP + S->Next;
 
 
    // Follow the hash table
    // Follow the hash table
-   while (S == Owner->GrpP && (HashIndex+1) < (signed)_count(Owner->HeaderP->GrpHashTable))
+   while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->HashTableSize)
    {
    {
       HashIndex++;
       HashIndex++;
-      S = Owner->GrpP + Owner->HeaderP->GrpHashTable[HashIndex];
+      S = Owner->GrpP + Owner->HeaderP->GrpHashTable()[HashIndex];
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -450,13 +434,13 @@ void pkgCache::PkgIterator::operator ++(int)
 {
 {
    // Follow the current links
    // Follow the current links
    if (S != Owner->PkgP)
    if (S != Owner->PkgP)
-      S = Owner->PkgP + S->NextPackage;
+      S = Owner->PkgP + S->Next;
 
 
    // Follow the hash table
    // Follow the hash table
-   while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable))
+   while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->HashTableSize)
    {
    {
       HashIndex++;
       HashIndex++;
-      S = Owner->PkgP + Owner->HeaderP->PkgHashTable[HashIndex];
+      S = Owner->PkgP + Owner->HeaderP->PkgHashTable()[HashIndex];
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -532,7 +516,10 @@ operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
       out << " -> " << candidate;
       out << " -> " << candidate;
    if ( newest != "none" && candidate != newest)
    if ( newest != "none" && candidate != newest)
       out << " | " << newest;
       out << " | " << newest;
-   out << " > ( " << string(Pkg.Section()==0?"none":Pkg.Section()) << " )";
+   if (Pkg->VersionList == 0)
+      out << " > ( none )";
+   else
+      out << " > ( " << string(Pkg.VersionList().Section()==0?"unknown":Pkg.VersionList().Section()) << " )";
    return out;
    return out;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1039,8 +1026,14 @@ bool pkgCache::PrvIterator::IsMultiArchImplicit() const
 {
 {
    pkgCache::PkgIterator const Owner = OwnerPkg();
    pkgCache::PkgIterator const Owner = OwnerPkg();
    pkgCache::PkgIterator const Parent = ParentPkg();
    pkgCache::PkgIterator const Parent = ParentPkg();
-   if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner->Name == Parent->Name)
+   if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner.Group()->Name == Parent.Group()->Name)
       return true;
       return true;
    return false;
    return false;
 }
 }
 									/*}}}*/
 									/*}}}*/
+APT_DEPRECATED APT_PURE const char * pkgCache::PkgIterator::Section() const {/*{{{*/
+   if (S->VersionList == 0)
+      return 0;
+   return VersionList().Section();
+}
+									/*}}}*/

+ 112 - 122
apt-pkg/pkgcache.h

@@ -79,11 +79,23 @@
 
 
 #include <string>
 #include <string>
 #include <time.h>
 #include <time.h>
+#include <stdint.h>
 
 
 #ifndef APT_8_CLEANER_HEADERS
 #ifndef APT_8_CLEANER_HEADERS
 using std::string;
 using std::string;
 #endif
 #endif
 
 
+// storing file sizes of indexes, which are way below 4 GB for now
+typedef uint32_t map_filesize_t;
+// each package/group/dependency gets an id
+typedef uint32_t map_id_t;
+// some files get an id, too, but in far less absolute numbers
+typedef uint16_t map_fileid_t;
+// relative pointer from cache start
+typedef uint32_t map_pointer_t;
+// same as the previous, but documented to be to a string item
+typedef map_pointer_t map_stringitem_t;
+
 class pkgVersioningSystem;
 class pkgVersioningSystem;
 class pkgCache								/*{{{*/
 class pkgCache								/*{{{*/
 {
 {
@@ -97,7 +109,6 @@ class pkgCache								/*{{{*/
    struct Description;
    struct Description;
    struct Provides;
    struct Provides;
    struct Dependency;
    struct Dependency;
-   struct StringItem;
    struct VerFile;
    struct VerFile;
    struct DescFile;
    struct DescFile;
    
    
@@ -158,8 +169,8 @@ class pkgCache								/*{{{*/
    std::string CacheFile;
    std::string CacheFile;
    MMap &Map;
    MMap &Map;
 
 
-   unsigned long sHash(const std::string &S) const APT_PURE;
-   unsigned long sHash(const char *S) const APT_PURE;
+   map_id_t sHash(const std::string &S) const APT_PURE;
+   map_id_t sHash(const char *S) const APT_PURE;
    
    
    public:
    public:
    
    
@@ -174,7 +185,6 @@ class pkgCache								/*{{{*/
    Description *DescP;
    Description *DescP;
    Provides *ProvideP;
    Provides *ProvideP;
    Dependency *DepP;
    Dependency *DepP;
-   StringItem *StringItemP;
    char *StrP;
    char *StrP;
 
 
    virtual bool ReMap(bool const &Errorchecks = true);
    virtual bool ReMap(bool const &Errorchecks = true);
@@ -183,8 +193,8 @@ class pkgCache								/*{{{*/
    inline void *DataEnd() {return ((unsigned char *)Map.Data()) + Map.Size();}
    inline void *DataEnd() {return ((unsigned char *)Map.Data()) + Map.Size();}
       
       
    // String hashing function (512 range)
    // String hashing function (512 range)
-   inline unsigned long Hash(const std::string &S) const {return sHash(S);}
-   inline unsigned long Hash(const char *S) const {return sHash(S);}
+   inline map_id_t Hash(const std::string &S) const {return sHash(S);}
+   inline map_id_t Hash(const char *S) const {return sHash(S);}
 
 
    // Useful transformation things
    // Useful transformation things
    const char *Priority(unsigned char Priority);
    const char *Priority(unsigned char Priority);
@@ -218,7 +228,7 @@ class pkgCache								/*{{{*/
 
 
 private:
 private:
    bool MultiArchEnabled;
    bool MultiArchEnabled;
-   PkgIterator SingleArchFindPkg(const std::string &Name);
+   APT_HIDDEN PkgIterator SingleArchFindPkg(const std::string &Name);
 };
 };
 									/*}}}*/
 									/*}}}*/
 // Header structure							/*{{{*/
 // Header structure							/*{{{*/
@@ -263,37 +273,31 @@ struct pkgCache::Header
        These indicate the number of each structure contained in the cache.
        These indicate the number of each structure contained in the cache.
        PackageCount is especially useful for generating user state structures.
        PackageCount is especially useful for generating user state structures.
        See Package::Id for more info. */
        See Package::Id for more info. */
-   unsigned long GroupCount;
-   unsigned long PackageCount;
-   unsigned long VersionCount;
-   unsigned long DescriptionCount;
-   unsigned long DependsCount;
-   unsigned long PackageFileCount;
-   unsigned long VerFileCount;
-   unsigned long DescFileCount;
-   unsigned long ProvidesCount;
+   map_id_t GroupCount;
+   map_id_t PackageCount;
+   map_id_t VersionCount;
+   map_id_t DescriptionCount;
+   map_id_t DependsCount;
+   map_fileid_t PackageFileCount;
+   map_fileid_t VerFileCount;
+   map_fileid_t DescFileCount;
+   map_id_t ProvidesCount;
 
 
    /** \brief index of the first PackageFile structure
    /** \brief index of the first PackageFile structure
 
 
        The PackageFile structures are singly linked lists that represent
        The PackageFile structures are singly linked lists that represent
        all package files that have been merged into the cache. */
        all package files that have been merged into the cache. */
-   map_ptrloc FileList;
-   /** \brief index of the first StringItem structure
-
-       The cache contains a list of all the unique strings (StringItems).
-       The parser reads this list into memory so it can match strings
-       against it.*/
-   map_ptrloc StringList;
+   map_pointer_t FileList;
    /** \brief String representing the version system used */
    /** \brief String representing the version system used */
-   map_ptrloc VerSysName;
+   map_pointer_t VerSysName;
    /** \brief native architecture the cache was built against */
    /** \brief native architecture the cache was built against */
-   map_ptrloc Architecture;
+   map_pointer_t Architecture;
    /** \brief all architectures the cache was built against */
    /** \brief all architectures the cache was built against */
-   map_ptrloc Architectures;
+   map_pointer_t Architectures;
    /** \brief The maximum size of a raw entry from the original Package file */
    /** \brief The maximum size of a raw entry from the original Package file */
-   unsigned long MaxVerFileSize;
+   map_filesize_t MaxVerFileSize;
    /** \brief The maximum size of a raw entry from the original Translation file */
    /** \brief The maximum size of a raw entry from the original Translation file */
-   unsigned long MaxDescFileSize;
+   map_filesize_t MaxDescFileSize;
 
 
    /** \brief The Pool structures manage the allocation pools that the generator uses
    /** \brief The Pool structures manage the allocation pools that the generator uses
 
 
@@ -304,23 +308,23 @@ struct pkgCache::Header
        stores this information so future additions can make use of any unused pool
        stores this information so future additions can make use of any unused pool
        blocks. */
        blocks. */
    DynamicMMap::Pool Pools[9];
    DynamicMMap::Pool Pools[9];
-   
+
    /** \brief hash tables providing rapid group/package name lookup
    /** \brief hash tables providing rapid group/package name lookup
 
 
-       Each group/package name is inserted into the hash table using pkgCache::Hash(const &string)
+       Each group/package name is inserted into a hash table using pkgCache::Hash(const &string)
        By iterating over each entry in the hash table it is possible to iterate over
        By iterating over each entry in the hash table it is possible to iterate over
        the entire list of packages. Hash Collisions are handled with a singly linked
        the entire list of packages. Hash Collisions are handled with a singly linked
        list of packages based at the hash item. The linked list contains only
        list of packages based at the hash item. The linked list contains only
        packages that match the hashing function.
        packages that match the hashing function.
        In the PkgHashTable is it possible that multiple packages have the same name -
        In the PkgHashTable is it possible that multiple packages have the same name -
        these packages are stored as a sequence in the list.
        these packages are stored as a sequence in the list.
-
-       Beware: The Hashmethod assumes that the hash table sizes are equal */
-   map_ptrloc PkgHashTable[2*1048];
-   map_ptrloc GrpHashTable[2*1048];
+       The size of both tables is the same. */
+   unsigned int HashTableSize;
+   map_pointer_t * PkgHashTable() const { return (map_pointer_t*) (this + 1); }
+   map_pointer_t * GrpHashTable() const { return PkgHashTable() + HashTableSize; }
 
 
    /** \brief Size of the complete cache file */
    /** \brief Size of the complete cache file */
-   unsigned long  CacheFileSize;
+   unsigned long long CacheFileSize;
 
 
    bool CheckSizes(Header &Against) const APT_PURE;
    bool CheckSizes(Header &Against) const APT_PURE;
    Header();
    Header();
@@ -336,17 +340,17 @@ struct pkgCache::Header
 struct pkgCache::Group
 struct pkgCache::Group
 {
 {
    /** \brief Name of the group */
    /** \brief Name of the group */
-   map_ptrloc Name;		// StringItem
+   map_stringitem_t Name;
 
 
    // Linked List
    // Linked List
    /** \brief Link to the first package which belongs to the group */
    /** \brief Link to the first package which belongs to the group */
-   map_ptrloc FirstPackage;	// Package
+   map_pointer_t FirstPackage;	// Package
    /** \brief Link to the last package which belongs to the group */
    /** \brief Link to the last package which belongs to the group */
-   map_ptrloc LastPackage;	// Package
+   map_pointer_t LastPackage;	// Package
    /** \brief Link to the next Group */
    /** \brief Link to the next Group */
-   map_ptrloc Next;		// Group
+   map_pointer_t Next;		// Group
    /** \brief unique sequel ID */
    /** \brief unique sequel ID */
-   unsigned int ID;
+   map_id_t ID;
 
 
 };
 };
 									/*}}}*/
 									/*}}}*/
@@ -364,10 +368,13 @@ struct pkgCache::Group
 */
 */
 struct pkgCache::Package
 struct pkgCache::Package
 {
 {
-   /** \brief Name of the package */
-   map_ptrloc Name;              // StringItem
+   /** \brief Name of the package
+    * Note that the access method Name() will remain. It is just this data member
+    * deprecated as this information is already stored and available via the
+    * associated Group – so it is wasting precious binary cache space */
+   APT_DEPRECATED map_stringitem_t Name;
    /** \brief Architecture of the package */
    /** \brief Architecture of the package */
-   map_ptrloc Arch;              // StringItem
+   map_stringitem_t Arch;
    /** \brief Base of a singly linked list of versions
    /** \brief Base of a singly linked list of versions
 
 
        Each structure represents a unique version of the package.
        Each structure represents a unique version of the package.
@@ -377,24 +384,19 @@ struct pkgCache::Package
        versions of a package can be cleanly handled by the system.
        versions of a package can be cleanly handled by the system.
        Furthermore, this linked list is guaranteed to be sorted
        Furthermore, this linked list is guaranteed to be sorted
        from Highest version to lowest version with no duplicate entries. */
        from Highest version to lowest version with no duplicate entries. */
-   map_ptrloc VersionList;       // Version
+   map_pointer_t VersionList;       // Version
    /** \brief index to the installed version */
    /** \brief index to the installed version */
-   map_ptrloc CurrentVer;        // Version
-   /** \brief indicates the deduced section
-
-       Should be the index to the string "Unknown" or to the section
-       of the last parsed item. */
-   map_ptrloc Section;           // StringItem
+   map_pointer_t CurrentVer;        // Version
    /** \brief index of the group this package belongs to */
    /** \brief index of the group this package belongs to */
-   map_ptrloc Group;             // Group the Package belongs to
+   map_pointer_t Group;             // Group the Package belongs to
 
 
    // Linked list
    // Linked list
    /** \brief Link to the next package in the same bucket */
    /** \brief Link to the next package in the same bucket */
-   map_ptrloc NextPackage;       // Package
+   map_pointer_t Next;       // Package
    /** \brief List of all dependencies on this package */
    /** \brief List of all dependencies on this package */
-   map_ptrloc RevDepends;        // Dependency
+   map_pointer_t RevDepends;        // Dependency
    /** \brief List of all "packages" this package provide */
    /** \brief List of all "packages" this package provide */
-   map_ptrloc ProvidesList;      // Provides
+   map_pointer_t ProvidesList;      // Provides
 
 
    // Install/Remove/Purge etc
    // Install/Remove/Purge etc
    /** \brief state that the user wishes the package to be in */
    /** \brief state that the user wishes the package to be in */
@@ -414,7 +416,7 @@ struct pkgCache::Package
        This allows clients to create an array of size PackageCount and use it to store
        This allows clients to create an array of size PackageCount and use it to store
        state information for the package map. For instance the status file emitter uses
        state information for the package map. For instance the status file emitter uses
        this to track which packages have been emitted already. */
        this to track which packages have been emitted already. */
-   unsigned int ID;
+   map_id_t ID;
    /** \brief some useful indicators of the package's state */
    /** \brief some useful indicators of the package's state */
    unsigned long Flags;
    unsigned long Flags;
 };
 };
@@ -428,30 +430,30 @@ struct pkgCache::Package
 struct pkgCache::PackageFile
 struct pkgCache::PackageFile
 {
 {
    /** \brief physical disk file that this PackageFile represents */
    /** \brief physical disk file that this PackageFile represents */
-   map_ptrloc FileName;        // StringItem
+   map_stringitem_t FileName;
    /** \brief the release information
    /** \brief the release information
 
 
        Please see the files document for a description of what the
        Please see the files document for a description of what the
        release information means. */
        release information means. */
-   map_ptrloc Archive;         // StringItem
-   map_ptrloc Codename;        // StringItem
-   map_ptrloc Component;       // StringItem
-   map_ptrloc Version;         // StringItem
-   map_ptrloc Origin;          // StringItem
-   map_ptrloc Label;           // StringItem
-   map_ptrloc Architecture;    // StringItem
+   map_stringitem_t Archive;
+   map_stringitem_t Codename;
+   map_stringitem_t Component;
+   map_stringitem_t Version;
+   map_stringitem_t Origin;
+   map_stringitem_t Label;
+   map_stringitem_t Architecture;
    /** \brief The site the index file was fetched from */
    /** \brief The site the index file was fetched from */
-   map_ptrloc Site;            // StringItem
+   map_stringitem_t Site;
    /** \brief indicates what sort of index file this is
    /** \brief indicates what sort of index file this is
 
 
        @TODO enumerate at least the possible indexes */
        @TODO enumerate at least the possible indexes */
-   map_ptrloc IndexType;       // StringItem
+   map_stringitem_t IndexType;
    /** \brief Size of the file
    /** \brief Size of the file
 
 
        Used together with the modification time as a
        Used together with the modification time as a
        simple check to ensure that the Packages
        simple check to ensure that the Packages
        file has not been altered since Cache generation. */
        file has not been altered since Cache generation. */
-   unsigned long Size;
+   map_filesize_t Size;
    /** \brief Modification time for the file */
    /** \brief Modification time for the file */
    time_t mtime;
    time_t mtime;
 
 
@@ -460,9 +462,9 @@ struct pkgCache::PackageFile
 
 
    // Linked list
    // Linked list
    /** \brief Link to the next PackageFile in the Cache */
    /** \brief Link to the next PackageFile in the Cache */
-   map_ptrloc NextFile;        // PackageFile
+   map_pointer_t NextFile;        // PackageFile
    /** \brief unique sequel ID */
    /** \brief unique sequel ID */
-   unsigned int ID;
+   map_fileid_t ID;
 };
 };
 									/*}}}*/
 									/*}}}*/
 // VerFile structure							/*{{{*/
 // VerFile structure							/*{{{*/
@@ -473,13 +475,13 @@ struct pkgCache::PackageFile
 struct pkgCache::VerFile
 struct pkgCache::VerFile
 {
 {
    /** \brief index of the package file that this version was found in */
    /** \brief index of the package file that this version was found in */
-   map_ptrloc File;           // PackageFile
+   map_pointer_t File;           // PackageFile
    /** \brief next step in the linked list */
    /** \brief next step in the linked list */
-   map_ptrloc NextFile;       // PkgVerFile
+   map_pointer_t NextFile;       // PkgVerFile
    /** \brief position in the package file */
    /** \brief position in the package file */
-   map_ptrloc Offset;         // File offset
+   map_filesize_t Offset;         // File offset
    /** @TODO document pkgCache::VerFile::Size */
    /** @TODO document pkgCache::VerFile::Size */
-   unsigned long Size;
+   map_filesize_t Size;
 };
 };
 									/*}}}*/
 									/*}}}*/
 // DescFile structure							/*{{{*/
 // DescFile structure							/*{{{*/
@@ -487,13 +489,13 @@ struct pkgCache::VerFile
 struct pkgCache::DescFile
 struct pkgCache::DescFile
 {
 {
    /** \brief index of the file that this description was found in */
    /** \brief index of the file that this description was found in */
-   map_ptrloc File;           // PackageFile
+   map_pointer_t File;           // PackageFile
    /** \brief next step in the linked list */
    /** \brief next step in the linked list */
-   map_ptrloc NextFile;       // PkgVerFile
+   map_pointer_t NextFile;       // PkgVerFile
    /** \brief position in the file */
    /** \brief position in the file */
-   map_ptrloc Offset;         // File offset
+   map_filesize_t Offset;         // File offset
    /** @TODO document pkgCache::DescFile::Size */
    /** @TODO document pkgCache::DescFile::Size */
-   unsigned long Size;
+   map_filesize_t Size;
 };
 };
 									/*}}}*/
 									/*}}}*/
 // Version structure							/*{{{*/
 // Version structure							/*{{{*/
@@ -505,9 +507,15 @@ struct pkgCache::DescFile
 struct pkgCache::Version
 struct pkgCache::Version
 {
 {
    /** \brief complete version string */
    /** \brief complete version string */
-   map_ptrloc VerStr;            // StringItem
+   map_stringitem_t VerStr;
    /** \brief section this version is filled in */
    /** \brief section this version is filled in */
-   map_ptrloc Section;           // StringItem
+   map_stringitem_t Section;
+   /** \brief source package name this version comes from
+      Always contains the name, even if it is the same as the binary name */
+   map_stringitem_t SourcePkgName;
+   /** \brief source version this version comes from
+      Always contains the version string, even if it is the same as the binary version */
+   map_stringitem_t SourceVerStr;
 
 
    /** \brief Multi-Arch capabilities of a package version */
    /** \brief Multi-Arch capabilities of a package version */
    enum VerMultiArch { None = 0, /*!< is the default and doesn't trigger special behaviour */
    enum VerMultiArch { None = 0, /*!< is the default and doesn't trigger special behaviour */
@@ -529,33 +537,33 @@ struct pkgCache::Version
        applies to. If FileList is 0 then this is a blank version.
        applies to. If FileList is 0 then this is a blank version.
        The structure should also have a 0 in all other fields excluding
        The structure should also have a 0 in all other fields excluding
        pkgCache::Version::VerStr and Possibly pkgCache::Version::NextVer. */
        pkgCache::Version::VerStr and Possibly pkgCache::Version::NextVer. */
-   map_ptrloc FileList;          // VerFile
+   map_pointer_t FileList;          // VerFile
    /** \brief next (lower or equal) version in the linked list */
    /** \brief next (lower or equal) version in the linked list */
-   map_ptrloc NextVer;           // Version
+   map_pointer_t NextVer;           // Version
    /** \brief next description in the linked list */
    /** \brief next description in the linked list */
-   map_ptrloc DescriptionList;   // Description
+   map_pointer_t DescriptionList;   // Description
    /** \brief base of the dependency list */
    /** \brief base of the dependency list */
-   map_ptrloc DependsList;       // Dependency
+   map_pointer_t DependsList;       // Dependency
    /** \brief links to the owning package
    /** \brief links to the owning package
 
 
        This allows reverse dependencies to determine the package */
        This allows reverse dependencies to determine the package */
-   map_ptrloc ParentPkg;         // Package
+   map_pointer_t ParentPkg;         // Package
    /** \brief list of pkgCache::Provides */
    /** \brief list of pkgCache::Provides */
-   map_ptrloc ProvidesList;      // Provides
+   map_pointer_t ProvidesList;      // Provides
 
 
    /** \brief archive size for this version
    /** \brief archive size for this version
 
 
        For Debian this is the size of the .deb file. */
        For Debian this is the size of the .deb file. */
-   unsigned long long Size;      // These are the .deb size
+   uint64_t Size; // These are the .deb size
    /** \brief uncompressed size for this version */
    /** \brief uncompressed size for this version */
-   unsigned long long InstalledSize;
+   uint64_t InstalledSize;
    /** \brief characteristic value representing this version
    /** \brief characteristic value representing this version
 
 
        No two packages in existence should have the same VerStr
        No two packages in existence should have the same VerStr
        and Hash with different contents. */
        and Hash with different contents. */
    unsigned short Hash;
    unsigned short Hash;
    /** \brief unique sequel ID */
    /** \brief unique sequel ID */
-   unsigned int ID;
+   map_id_t ID;
    /** \brief parsed priority value */
    /** \brief parsed priority value */
    unsigned char Priority;
    unsigned char Priority;
 };
 };
@@ -568,22 +576,22 @@ struct pkgCache::Description
 
 
        If the value has a 0 length then this is read using the Package
        If the value has a 0 length then this is read using the Package
        file else the Translation-CODE file is used. */
        file else the Translation-CODE file is used. */
-   map_ptrloc language_code;     // StringItem
+   map_stringitem_t language_code;
    /** \brief MD5sum of the original description
    /** \brief MD5sum of the original description
 
 
        Used to map Translations of a description to a version
        Used to map Translations of a description to a version
        and to check that the Translation is up-to-date. */
        and to check that the Translation is up-to-date. */
-   map_ptrloc md5sum;            // StringItem
+   map_stringitem_t md5sum;
 
 
    /** @TODO document pkgCache::Description::FileList */
    /** @TODO document pkgCache::Description::FileList */
-   map_ptrloc FileList;          // DescFile
+   map_pointer_t FileList;          // DescFile
    /** \brief next translation for this description */
    /** \brief next translation for this description */
-   map_ptrloc NextDesc;          // Description
+   map_pointer_t NextDesc;          // Description
    /** \brief the text is a description of this package */
    /** \brief the text is a description of this package */
-   map_ptrloc ParentPkg;         // Package
+   map_pointer_t ParentPkg;         // Package
 
 
    /** \brief unique sequel ID */
    /** \brief unique sequel ID */
-   unsigned int ID;
+   map_id_t ID;
 };
 };
 									/*}}}*/
 									/*}}}*/
 // Dependency structure							/*{{{*/
 // Dependency structure							/*{{{*/
@@ -596,21 +604,21 @@ struct pkgCache::Description
 struct pkgCache::Dependency
 struct pkgCache::Dependency
 {
 {
    /** \brief string of the version the dependency is applied against */
    /** \brief string of the version the dependency is applied against */
-   map_ptrloc Version;         // StringItem
+   map_stringitem_t Version;
    /** \brief index of the package this depends applies to
    /** \brief index of the package this depends applies to
 
 
        The generator will - if the package does not already exist -
        The generator will - if the package does not already exist -
        create a blank (no version records) package. */
        create a blank (no version records) package. */
-   map_ptrloc Package;         // Package
+   map_pointer_t Package;         // Package
    /** \brief next dependency of this version */
    /** \brief next dependency of this version */
-   map_ptrloc NextDepends;     // Dependency
+   map_pointer_t NextDepends;     // Dependency
    /** \brief next reverse dependency of this package */
    /** \brief next reverse dependency of this package */
-   map_ptrloc NextRevDepends;  // Dependency
+   map_pointer_t NextRevDepends;  // Dependency
    /** \brief version of the package which has the reverse depends */
    /** \brief version of the package which has the reverse depends */
-   map_ptrloc ParentVer;       // Version
+   map_pointer_t ParentVer;       // Version
 
 
    /** \brief unique sequel ID */
    /** \brief unique sequel ID */
-   map_ptrloc ID;
+   map_id_t ID;
    /** \brief Dependency type - Depends, Recommends, Conflicts, etc */
    /** \brief Dependency type - Depends, Recommends, Conflicts, etc */
    unsigned char Type;
    unsigned char Type;
    /** \brief comparison operator specified on the depends line
    /** \brief comparison operator specified on the depends line
@@ -631,39 +639,21 @@ struct pkgCache::Dependency
 struct pkgCache::Provides
 struct pkgCache::Provides
 {
 {
    /** \brief index of the package providing this */
    /** \brief index of the package providing this */
-   map_ptrloc ParentPkg;        // Package
+   map_pointer_t ParentPkg;        // Package
    /** \brief index of the version this provide line applies to */
    /** \brief index of the version this provide line applies to */
-   map_ptrloc Version;          // Version
+   map_pointer_t Version;          // Version
    /** \brief version in the provides line (if any)
    /** \brief version in the provides line (if any)
 
 
        This version allows dependencies to depend on specific versions of a
        This version allows dependencies to depend on specific versions of a
        Provides, as well as allowing Provides to override existing packages.
        Provides, as well as allowing Provides to override existing packages.
        This is experimental. Note that Debian doesn't allow versioned provides */
        This is experimental. Note that Debian doesn't allow versioned provides */
-   map_ptrloc ProvideVersion;   // StringItem
+   map_stringitem_t ProvideVersion;
    /** \brief next provides (based of package) */
    /** \brief next provides (based of package) */
-   map_ptrloc NextProvides;     // Provides
+   map_pointer_t NextProvides;     // Provides
    /** \brief next provides (based of version) */
    /** \brief next provides (based of version) */
-   map_ptrloc NextPkgProv;      // Provides
+   map_pointer_t NextPkgProv;      // Provides
 };
 };
 									/*}}}*/
 									/*}}}*/
-// StringItem structure							/*{{{*/
-/** \brief used for generating single instances of strings
-
-    Some things like Section Name are are useful to have as unique tags.
-    It is part of a linked list based at pkgCache::Header::StringList
-
-    All strings are simply inlined any place in the file that is natural
-    for the writer. The client should make no assumptions about the positioning
-    of strings. All StringItems should be null-terminated. */
-struct pkgCache::StringItem
-{
-   /** \brief string this refers to */
-   map_ptrloc String;        // StringItem
-   /** \brief Next link in the chain */
-   map_ptrloc NextItem;      // StringItem
-};
-									/*}}}*/
-
 
 
 inline char const * pkgCache::NativeArch()
 inline char const * pkgCache::NativeArch()
 	{ return StrP + HeaderP->Architecture; }
 	{ return StrP + HeaderP->Architecture; }

+ 115 - 140
apt-pkg/pkgcachegen.cc

@@ -57,8 +57,7 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
 		    FoundFileDeps(0)
 		    FoundFileDeps(0)
 {
 {
    CurrentFile = 0;
    CurrentFile = 0;
-   memset(UniqHash,0,sizeof(UniqHash));
-   
+
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return;
       return;
 
 
@@ -73,13 +72,16 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
 
 
       // Starting header
       // Starting header
       *Cache.HeaderP = pkgCache::Header();
       *Cache.HeaderP = pkgCache::Header();
-      map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+
+      // make room for the hashtables for packages and groups
+      if (Map.RawAllocate(2 * (Cache.HeaderP->HashTableSize * sizeof(map_pointer_t))) == 0)
+	 return;
+
+      map_stringitem_t const idxVerSysName = WriteStringInMap(_system->VS->Label);
       if (unlikely(idxVerSysName == 0))
       if (unlikely(idxVerSysName == 0))
 	 return;
 	 return;
       Cache.HeaderP->VerSysName = idxVerSysName;
       Cache.HeaderP->VerSysName = idxVerSysName;
-      // this pointer is set in ReMap, but we need it now for WriteUniqString
-      Cache.StringItemP = (pkgCache::StringItem *)Map.Data();
-      map_ptrloc const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
+      map_stringitem_t const idxArchitecture = StoreString(MIXED, _config->Find("APT::Architecture"));
       if (unlikely(idxArchitecture == 0))
       if (unlikely(idxArchitecture == 0))
 	 return;
 	 return;
       Cache.HeaderP->Architecture = idxArchitecture;
       Cache.HeaderP->Architecture = idxArchitecture;
@@ -91,7 +93,7 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
 	 std::string list = *a;
 	 std::string list = *a;
 	 for (++a; a != archs.end(); ++a)
 	 for (++a; a != archs.end(); ++a)
 	    list.append(",").append(*a);
 	    list.append(",").append(*a);
-	 map_ptrloc const idxArchitectures = WriteStringInMap(list);
+	 map_stringitem_t const idxArchitectures = WriteStringInMap(list);
 	 if (unlikely(idxArchitectures == 0))
 	 if (unlikely(idxArchitectures == 0))
 	    return;
 	    return;
 	 Cache.HeaderP->Architectures = idxArchitectures;
 	 Cache.HeaderP->Architectures = idxArchitectures;
@@ -110,9 +112,9 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
       {
       {
 	 _error->Error(_("Cache has an incompatible versioning system"));
 	 _error->Error(_("Cache has an incompatible versioning system"));
 	 return;
 	 return;
-      }      
+      }
    }
    }
-   
+
    Cache.HeaderP->Dirty = true;
    Cache.HeaderP->Dirty = true;
    Map.Sync(0,sizeof(pkgCache::Header));
    Map.Sync(0,sizeof(pkgCache::Header));
 }
 }
@@ -144,10 +146,6 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
 
 
    CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap;
    CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap;
 
 
-   for (size_t i = 0; i < _count(UniqHash); ++i)
-      if (UniqHash[i] != 0)
-	 UniqHash[i] += (pkgCache::StringItem const * const) newMap - (pkgCache::StringItem const * const) oldMap;
-
    for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
    for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
 	i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
 	i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
       (*i)->ReMap(oldMap, newMap);
       (*i)->ReMap(oldMap, newMap);
@@ -171,27 +169,27 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
       (*i)->ReMap(oldMap, newMap);
       (*i)->ReMap(oldMap, newMap);
 }									/*}}}*/
 }									/*}}}*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
-map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String,
+map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String,
 					const unsigned long &Len) {
 					const unsigned long &Len) {
    void const * const oldMap = Map.Data();
    void const * const oldMap = Map.Data();
-   map_ptrloc const index = Map.WriteString(String, Len);
+   map_stringitem_t const index = Map.WriteString(String, Len);
    if (index != 0)
    if (index != 0)
       ReMap(oldMap, Map.Data());
       ReMap(oldMap, Map.Data());
    return index;
    return index;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
-map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) {
+map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String) {
    void const * const oldMap = Map.Data();
    void const * const oldMap = Map.Data();
-   map_ptrloc const index = Map.WriteString(String);
+   map_stringitem_t const index = Map.WriteString(String);
    if (index != 0)
    if (index != 0)
       ReMap(oldMap, Map.Data());
       ReMap(oldMap, Map.Data());
    return index;
    return index;
 }
 }
 									/*}}}*/
 									/*}}}*/
-map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
+map_pointer_t pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
    void const * const oldMap = Map.Data();
    void const * const oldMap = Map.Data();
-   map_ptrloc const index = Map.Allocate(size);
+   map_pointer_t const index = Map.Allocate(size);
    if (index != 0)
    if (index != 0)
       ReMap(oldMap, Map.Data());
       ReMap(oldMap, Map.Data());
    return index;
    return index;
@@ -271,16 +269,16 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       }
       }
    }
    }
 
 
-   if (Cache.HeaderP->PackageCount >= (1ULL<<sizeof(Cache.PkgP->ID)*8)-1)
+   if (Cache.HeaderP->PackageCount >= std::numeric_limits<map_id_t>::max())
       return _error->Error(_("Wow, you exceeded the number of package "
       return _error->Error(_("Wow, you exceeded the number of package "
 			     "names this APT is capable of."));
 			     "names this APT is capable of."));
-   if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
+   if (Cache.HeaderP->VersionCount >= std::numeric_limits<map_id_t>::max())
       return _error->Error(_("Wow, you exceeded the number of versions "
       return _error->Error(_("Wow, you exceeded the number of versions "
 			     "this APT is capable of."));
 			     "this APT is capable of."));
-   if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
+   if (Cache.HeaderP->DescriptionCount >= std::numeric_limits<map_id_t>::max())
       return _error->Error(_("Wow, you exceeded the number of descriptions "
       return _error->Error(_("Wow, you exceeded the number of descriptions "
 			     "this APT is capable of."));
 			     "this APT is capable of."));
-   if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
+   if (Cache.HeaderP->DependsCount >= std::numeric_limits<map_id_t>::max())
       return _error->Error(_("Wow, you exceeded the number of dependencies "
       return _error->Error(_("Wow, you exceeded the number of dependencies "
 			     "this APT is capable of."));
 			     "this APT is capable of."));
 
 
@@ -331,7 +329,7 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
       if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5)
       if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5)
 	 continue;
 	 continue;
 
 
-      map_ptrloc md5idx = VerDesc->md5sum;
+      map_stringitem_t md5idx = VerDesc->md5sum;
       for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
       for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
       {
       {
 	 // don't add a new description if we have one for the given
 	 // don't add a new description if we have one for the given
@@ -355,7 +353,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
 {
 {
    pkgCache::VerIterator Ver = Pkg.VersionList();
    pkgCache::VerIterator Ver = Pkg.VersionList();
    Dynamic<pkgCache::VerIterator> DynVer(Ver);
    Dynamic<pkgCache::VerIterator> DynVer(Ver);
-   map_ptrloc *LastVer = &Pkg->VersionList;
+   map_pointer_t *LastVer = &Pkg->VersionList;
    void const * oldMap = Map.Data();
    void const * oldMap = Map.Data();
 
 
    unsigned short const Hash = List.VersionHash();
    unsigned short const Hash = List.VersionHash();
@@ -364,7 +362,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
       /* We know the list is sorted so we use that fact in the search.
       /* We know the list is sorted so we use that fact in the search.
          Insertion of new versions is done with correct sorting */
          Insertion of new versions is done with correct sorting */
       int Res = 1;
       int Res = 1;
-      for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
+      for (; Ver.end() == false; LastVer = &Ver->NextVer, ++Ver)
       {
       {
 	 Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
 	 Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
 	 // Version is higher as current version - insert here
 	 // Version is higher as current version - insert here
@@ -400,13 +398,13 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
    }
    }
 
 
    // Add a new version
    // Add a new version
-   map_ptrloc const verindex = NewVersion(Ver, Version, Pkg.Index(), Hash, *LastVer);
+   map_pointer_t const verindex = NewVersion(Ver, Version, Pkg.Index(), Hash, *LastVer);
    if (verindex == 0 && _error->PendingError())
    if (verindex == 0 && _error->PendingError())
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
 			   Pkg.Name(), "NewVersion", 1);
 			   Pkg.Name(), "NewVersion", 1);
 
 
    if (oldMap != Map.Data())
    if (oldMap != Map.Data())
-	 LastVer += (map_ptrloc const * const) Map.Data() - (map_ptrloc const * const) oldMap;
+	 LastVer += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
    *LastVer = verindex;
    *LastVer = verindex;
 
 
    if (unlikely(List.NewVersion(Ver) == false))
    if (unlikely(List.NewVersion(Ver) == false))
@@ -467,7 +465,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
 		   D.ParentPkg().Group() == Grp)
 		   D.ParentPkg().Group() == Grp)
 		  continue;
 		  continue;
 
 
-	       map_ptrloc *OldDepLast = NULL;
+	       map_pointer_t *OldDepLast = NULL;
 	       pkgCache::VerIterator ConVersion = D.ParentVer();
 	       pkgCache::VerIterator ConVersion = D.ParentVer();
 	       Dynamic<pkgCache::VerIterator> DynV(ConVersion);
 	       Dynamic<pkgCache::VerIterator> DynV(ConVersion);
 	       // duplicate the Conflicts/Breaks/Replaces for :none arch
 	       // duplicate the Conflicts/Breaks/Replaces for :none arch
@@ -509,7 +507,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
    }
    }
 
 
    // We haven't found reusable descriptions, so add the first description(s)
    // We haven't found reusable descriptions, so add the first description(s)
-   map_ptrloc md5idx = Ver->DescriptionList == 0 ? 0 : Ver.DescriptionList()->md5sum;
+   map_stringitem_t md5idx = Ver->DescriptionList == 0 ? 0 : Ver.DescriptionList()->md5sum;
    std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
    std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
    for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
    for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
       if (AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx) == false)
       if (AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx) == false)
@@ -517,12 +515,12 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver, std::string const &lang, MD5SumValue const &CurMd5, map_ptrloc &md5idx) /*{{{*/
+bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver, std::string const &lang, MD5SumValue const &CurMd5, map_stringitem_t &md5idx) /*{{{*/
 {
 {
    pkgCache::DescIterator Desc;
    pkgCache::DescIterator Desc;
    Dynamic<pkgCache::DescIterator> DynDesc(Desc);
    Dynamic<pkgCache::DescIterator> DynDesc(Desc);
 
 
-   map_ptrloc const descindex = NewDescription(Desc, lang, CurMd5, md5idx);
+   map_pointer_t const descindex = NewDescription(Desc, lang, CurMd5, md5idx);
    if (unlikely(descindex == 0 && _error->PendingError()))
    if (unlikely(descindex == 0 && _error->PendingError()))
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
 	    Ver.ParentPkg().Name(), "NewDescription", 1);
 	    Ver.ParentPkg().Name(), "NewDescription", 1);
@@ -534,7 +532,7 @@ bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterato
    // that to be able to efficiently share these lists
    // that to be able to efficiently share these lists
    pkgCache::DescIterator VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
    pkgCache::DescIterator VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
    for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
    for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
-   map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
+   map_pointer_t * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
    *LastNextDesc = descindex;
    *LastNextDesc = descindex;
 
 
    if (NewFileDesc(Desc,List) == false)
    if (NewFileDesc(Desc,List) == false)
@@ -606,19 +604,19 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
       return true;
       return true;
 
 
    // Get a structure
    // Get a structure
-   map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group));
+   map_pointer_t const Group = AllocateInMap(sizeof(pkgCache::Group));
    if (unlikely(Group == 0))
    if (unlikely(Group == 0))
       return false;
       return false;
 
 
    Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
    Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
-   map_ptrloc const idxName = WriteStringInMap(Name);
+   map_stringitem_t const idxName = StoreString(PKGNAME, Name);
    if (unlikely(idxName == 0))
    if (unlikely(idxName == 0))
       return false;
       return false;
    Grp->Name = idxName;
    Grp->Name = idxName;
 
 
    // Insert it into the hash table
    // Insert it into the hash table
    unsigned long const Hash = Cache.Hash(Name);
    unsigned long const Hash = Cache.Hash(Name);
-   map_ptrloc *insertAt = &Cache.HeaderP->GrpHashTable[Hash];
+   map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTable()[Hash];
    while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
    while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
       insertAt = &(Cache.GrpP + *insertAt)->Next;
       insertAt = &(Cache.GrpP + *insertAt)->Next;
    Grp->Next = *insertAt;
    Grp->Next = *insertAt;
@@ -643,7 +641,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
 	 return true;
 	 return true;
 
 
    // Get a structure
    // Get a structure
-   map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package));
+   map_pointer_t const Package = AllocateInMap(sizeof(pkgCache::Package));
    if (unlikely(Package == 0))
    if (unlikely(Package == 0))
       return false;
       return false;
    Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
    Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
@@ -653,27 +651,34 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
    {
    {
       Grp->FirstPackage = Package;
       Grp->FirstPackage = Package;
       // Insert it into the hash table
       // Insert it into the hash table
-      unsigned long const Hash = Cache.Hash(Name);
-      map_ptrloc *insertAt = &Cache.HeaderP->PkgHashTable[Hash];
-      while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.PkgP + *insertAt)->Name) > 0)
-	 insertAt = &(Cache.PkgP + *insertAt)->NextPackage;
-      Pkg->NextPackage = *insertAt;
+      map_id_t const Hash = Cache.Hash(Name);
+      map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTable()[Hash];
+      while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0)
+	 insertAt = &(Cache.PkgP + *insertAt)->Next;
+      Pkg->Next = *insertAt;
       *insertAt = Package;
       *insertAt = Package;
    }
    }
    else // Group the Packages together
    else // Group the Packages together
    {
    {
       // this package is the new last package
       // this package is the new last package
       pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
       pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
-      Pkg->NextPackage = LastPkg->NextPackage;
-      LastPkg->NextPackage = Package;
+      Pkg->Next = LastPkg->Next;
+      LastPkg->Next = Package;
    }
    }
    Grp->LastPackage = Package;
    Grp->LastPackage = Package;
 
 
    // Set the name, arch and the ID
    // Set the name, arch and the ID
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
    Pkg->Name = Grp->Name;
    Pkg->Name = Grp->Name;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
    Pkg->Group = Grp.Index();
    Pkg->Group = Grp.Index();
    // all is mapped to the native architecture
    // all is mapped to the native architecture
-   map_ptrloc const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : WriteUniqString(Arch.c_str());
+   map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch);
    if (unlikely(idxArch == 0))
    if (unlikely(idxArch == 0))
       return false;
       return false;
    Pkg->Arch = idxArch;
    Pkg->Arch = idxArch;
@@ -690,14 +695,14 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G,
    // copy P.Arch() into a string here as a cache remap
    // copy P.Arch() into a string here as a cache remap
    // in NewDepends() later may alter the pointer location
    // in NewDepends() later may alter the pointer location
    string Arch = P.Arch() == NULL ? "" : P.Arch();
    string Arch = P.Arch() == NULL ? "" : P.Arch();
-   map_ptrloc *OldDepLast = NULL;
+   map_pointer_t *OldDepLast = NULL;
    /* MultiArch handling introduces a lot of implicit Dependencies:
    /* MultiArch handling introduces a lot of implicit Dependencies:
       - MultiArch: same → Co-Installable if they have the same version
       - MultiArch: same → Co-Installable if they have the same version
       - All others conflict with all other group members */
       - All others conflict with all other group members */
    bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
    bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
    pkgCache::PkgIterator D = G.PackageList();
    pkgCache::PkgIterator D = G.PackageList();
    Dynamic<pkgCache::PkgIterator> DynD(D);
    Dynamic<pkgCache::PkgIterator> DynD(D);
-   map_ptrloc const VerStrIdx = V->VerStr;
+   map_stringitem_t const VerStrIdx = V->VerStr;
    for (; D.end() != true; D = G.NextPkg(D))
    for (; D.end() != true; D = G.NextPkg(D))
    {
    {
       if (Arch == D.Arch() || D->VersionList == 0)
       if (Arch == D.Arch() || D->VersionList == 0)
@@ -730,11 +735,11 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V,
    /* MultiArch handling introduces a lot of implicit Dependencies:
    /* MultiArch handling introduces a lot of implicit Dependencies:
       - MultiArch: same → Co-Installable if they have the same version
       - MultiArch: same → Co-Installable if they have the same version
       - All others conflict with all other group members */
       - All others conflict with all other group members */
-   map_ptrloc *OldDepLast = NULL;
+   map_pointer_t *OldDepLast = NULL;
    bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
    bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
    if (coInstall == true)
    if (coInstall == true)
    {
    {
-      map_ptrloc const VerStrIdx = V->VerStr;
+      map_stringitem_t const VerStrIdx = V->VerStr;
       // Replaces: ${self}:other ( << ${binary:Version})
       // Replaces: ${self}:other ( << ${binary:Version})
       NewDepends(D, V, VerStrIdx,
       NewDepends(D, V, VerStrIdx,
 		 pkgCache::Dep::Less, pkgCache::Dep::Replaces,
 		 pkgCache::Dep::Less, pkgCache::Dep::Replaces,
@@ -763,15 +768,15 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
       return true;
       return true;
    
    
    // Get a structure
    // Get a structure
-   map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
+   map_pointer_t const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
    if (VerFile == 0)
    if (VerFile == 0)
-      return 0;
+      return false;
    
    
    pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
    pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
    VF->File = CurrentFile - Cache.PkgFileP;
    VF->File = CurrentFile - Cache.PkgFileP;
    
    
    // Link it to the end of the list
    // Link it to the end of the list
-   map_ptrloc *Last = &Ver->FileList;
+   map_pointer_t *Last = &Ver->FileList;
    for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; ++V)
    for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; ++V)
       Last = &V->NextFile;
       Last = &V->NextFile;
    VF->NextFile = *Last;
    VF->NextFile = *Last;
@@ -789,14 +794,14 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
 // CacheGenerator::NewVersion - Create a new Version 			/*{{{*/
 // CacheGenerator::NewVersion - Create a new Version 			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This puts a version structure in the linked list */
 /* This puts a version structure in the linked list */
-unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
+map_pointer_t pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
 					    const string &VerStr,
 					    const string &VerStr,
-					    map_ptrloc const ParentPkg,
-					    unsigned long const Hash,
-					    unsigned long Next)
+					    map_pointer_t const ParentPkg,
+					    unsigned short const Hash,
+					    map_pointer_t const Next)
 {
 {
    // Get a structure
    // Get a structure
-   map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version));
+   map_pointer_t const Version = AllocateInMap(sizeof(pkgCache::Version));
    if (Version == 0)
    if (Version == 0)
       return 0;
       return 0;
    
    
@@ -831,7 +836,7 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
       }
       }
    }
    }
    // haven't found the version string, so create
    // haven't found the version string, so create
-   map_ptrloc const idxVerStr = WriteStringInMap(VerStr);
+   map_stringitem_t const idxVerStr = StoreString(VERSIONNUMBER, VerStr);
    if (unlikely(idxVerStr == 0))
    if (unlikely(idxVerStr == 0))
       return 0;
       return 0;
    Ver->VerStr = idxVerStr;
    Ver->VerStr = idxVerStr;
@@ -848,7 +853,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
       return true;
       return true;
    
    
    // Get a structure
    // Get a structure
-   map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
+   map_pointer_t const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
    if (DescFile == 0)
    if (DescFile == 0)
       return false;
       return false;
 
 
@@ -856,7 +861,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
    DF->File = CurrentFile - Cache.PkgFileP;
    DF->File = CurrentFile - Cache.PkgFileP;
 
 
    // Link it to the end of the list
    // Link it to the end of the list
-   map_ptrloc *Last = &Desc->FileList;
+   map_pointer_t *Last = &Desc->FileList;
    for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; ++D)
    for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; ++D)
       Last = &D->NextFile;
       Last = &D->NextFile;
 
 
@@ -875,20 +880,20 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
 // CacheGenerator::NewDescription - Create a new Description		/*{{{*/
 // CacheGenerator::NewDescription - Create a new Description		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This puts a description structure in the linked list */
 /* This puts a description structure in the linked list */
-map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
+map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 					    const string &Lang,
 					    const string &Lang,
 					    const MD5SumValue &md5sum,
 					    const MD5SumValue &md5sum,
-					    map_ptrloc idxmd5str)
+					    map_stringitem_t const idxmd5str)
 {
 {
    // Get a structure
    // Get a structure
-   map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description));
+   map_pointer_t const Description = AllocateInMap(sizeof(pkgCache::Description));
    if (Description == 0)
    if (Description == 0)
       return 0;
       return 0;
 
 
    // Fill it in
    // Fill it in
    Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
    Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
    Desc->ID = Cache.HeaderP->DescriptionCount++;
    Desc->ID = Cache.HeaderP->DescriptionCount++;
-   map_ptrloc const idxlanguage_code = WriteUniqString(Lang);
+   map_stringitem_t const idxlanguage_code = StoreString(MIXED, Lang);
    if (unlikely(idxlanguage_code == 0))
    if (unlikely(idxlanguage_code == 0))
       return 0;
       return 0;
    Desc->language_code = idxlanguage_code;
    Desc->language_code = idxlanguage_code;
@@ -897,7 +902,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
       Desc->md5sum = idxmd5str;
       Desc->md5sum = idxmd5str;
    else
    else
    {
    {
-      map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value());
+      map_stringitem_t const idxmd5sum = WriteStringInMap(md5sum.Value());
       if (unlikely(idxmd5sum == 0))
       if (unlikely(idxmd5sum == 0))
 	 return 0;
 	 return 0;
       Desc->md5sum = idxmd5sum;
       Desc->md5sum = idxmd5sum;
@@ -915,9 +920,9 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 				   string const &Version,
 				   string const &Version,
 				   unsigned int const &Op,
 				   unsigned int const &Op,
 				   unsigned int const &Type,
 				   unsigned int const &Type,
-				   map_ptrloc* &OldDepLast)
+				   map_stringitem_t* &OldDepLast)
 {
 {
-   map_ptrloc index = 0;
+   map_stringitem_t index = 0;
    if (Version.empty() == false)
    if (Version.empty() == false)
    {
    {
       int const CmpOp = Op & 0x0F;
       int const CmpOp = Op & 0x0F;
@@ -928,25 +933,25 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
       if (index == 0)
       if (index == 0)
       {
       {
 	 void const * const oldMap = Map.Data();
 	 void const * const oldMap = Map.Data();
-	 index = WriteStringInMap(Version);
+	 index = StoreString(VERSIONNUMBER, Version);
 	 if (unlikely(index == 0))
 	 if (unlikely(index == 0))
 	    return false;
 	    return false;
 	 if (OldDepLast != 0 && oldMap != Map.Data())
 	 if (OldDepLast != 0 && oldMap != Map.Data())
-	    OldDepLast += (map_ptrloc const * const) Map.Data() - (map_ptrloc const * const) oldMap;
+	    OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
       }
       }
    }
    }
    return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast);
    return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast);
 }
 }
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 				   pkgCache::VerIterator &Ver,
 				   pkgCache::VerIterator &Ver,
-				   map_ptrloc const Version,
+				   map_pointer_t const Version,
 				   unsigned int const &Op,
 				   unsigned int const &Op,
 				   unsigned int const &Type,
 				   unsigned int const &Type,
-				   map_ptrloc* &OldDepLast)
+				   map_pointer_t* &OldDepLast)
 {
 {
    void const * const oldMap = Map.Data();
    void const * const oldMap = Map.Data();
    // Get a structure
    // Get a structure
-   map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
+   map_pointer_t const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
    if (unlikely(Dependency == 0))
    if (unlikely(Dependency == 0))
       return false;
       return false;
 
 
@@ -971,7 +976,7 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
       for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
       for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
 	 OldDepLast = &D->NextDepends;
 	 OldDepLast = &D->NextDepends;
    } else if (oldMap != Map.Data())
    } else if (oldMap != Map.Data())
-      OldDepLast += (map_ptrloc const * const) Map.Data() - (map_ptrloc const * const) oldMap;
+      OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
 
 
    Dep->NextDepends = *OldDepLast;
    Dep->NextDepends = *OldDepLast;
    *OldDepLast = Dep.Index();
    *OldDepLast = Dep.Index();
@@ -1036,7 +1041,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
       return true;
       return true;
    
    
    // Get a structure
    // Get a structure
-   map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
+   map_pointer_t const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
    if (unlikely(Provides == 0))
    if (unlikely(Provides == 0))
       return false;
       return false;
    Cache.HeaderP->ProvidesCount++;
    Cache.HeaderP->ProvidesCount++;
@@ -1048,7 +1053,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
    Prv->NextPkgProv = Ver->ProvidesList;
    Prv->NextPkgProv = Ver->ProvidesList;
    Ver->ProvidesList = Prv.Index();
    Ver->ProvidesList = Prv.Index();
    if (Version.empty() == false) {
    if (Version.empty() == false) {
-      map_ptrloc const idxProvideVersion = WriteString(Version);
+      map_stringitem_t const idxProvideVersion = WriteString(Version);
       Prv->ProvideVersion = idxProvideVersion;
       Prv->ProvideVersion = idxProvideVersion;
       if (unlikely(idxProvideVersion == 0))
       if (unlikely(idxProvideVersion == 0))
 	 return false;
 	 return false;
@@ -1083,14 +1088,14 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
 				   unsigned long Flags)
 				   unsigned long Flags)
 {
 {
    // Get some space for the structure
    // Get some space for the structure
-   map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile));
+   map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile));
    if (unlikely(idxFile == 0))
    if (unlikely(idxFile == 0))
       return false;
       return false;
    CurrentFile = Cache.PkgFileP + idxFile;
    CurrentFile = Cache.PkgFileP + idxFile;
 
 
    // Fill it in
    // Fill it in
-   map_ptrloc const idxFileName = WriteStringInMap(File);
-   map_ptrloc const idxSite = WriteUniqString(Site);
+   map_stringitem_t const idxFileName = WriteStringInMap(File);
+   map_stringitem_t const idxSite = StoreString(MIXED, Site);
    if (unlikely(idxFileName == 0 || idxSite == 0))
    if (unlikely(idxFileName == 0 || idxSite == 0))
       return false;
       return false;
    CurrentFile->FileName = idxFileName;
    CurrentFile->FileName = idxFileName;
@@ -1098,7 +1103,7 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
    CurrentFile->NextFile = Cache.HeaderP->FileList;
    CurrentFile->NextFile = Cache.HeaderP->FileList;
    CurrentFile->Flags = Flags;
    CurrentFile->Flags = Flags;
    CurrentFile->ID = Cache.HeaderP->PackageFileCount;
    CurrentFile->ID = Cache.HeaderP->PackageFileCount;
-   map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label);
+   map_stringitem_t const idxIndexType = StoreString(MIXED, Index.GetType()->Label);
    if (unlikely(idxIndexType == 0))
    if (unlikely(idxIndexType == 0))
       return false;
       return false;
    CurrentFile->IndexType = idxIndexType;
    CurrentFile->IndexType = idxIndexType;
@@ -1115,57 +1120,27 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is used to create handles to strings. Given the same text it
 /* This is used to create handles to strings. Given the same text it
    always returns the same number */
    always returns the same number */
-unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
+map_stringitem_t pkgCacheGenerator::StoreString(enum StringType const type, const char *S,
 						 unsigned int Size)
 						 unsigned int Size)
 {
 {
-   /* We use a very small transient hash table here, this speeds up generation
-      by a fair amount on slower machines */
-   pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)];
-   if (Bucket != 0 && 
-       stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0)
-      return Bucket->String;
-   
-   // Search for an insertion point
-   pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
-   int Res = 1;
-   map_ptrloc *Last = &Cache.HeaderP->StringList;
-   for (; I != Cache.StringItemP; Last = &I->NextItem, 
-        I = Cache.StringItemP + I->NextItem)
-   {
-      Res = stringcmp(S,S+Size,Cache.StrP + I->String);
-      if (Res >= 0)
-	 break;
-   }
-   
-   // Match
-   if (Res == 0)
-   {
-      Bucket = I;
-      return I->String;
-   }
-   
-   // Get a structure
-   void const * const oldMap = Map.Data();
-   map_ptrloc const Item = AllocateInMap(sizeof(pkgCache::StringItem));
-   if (Item == 0)
-      return 0;
-
-   map_ptrloc const idxString = WriteStringInMap(S,Size);
-   if (unlikely(idxString == 0))
-      return 0;
-   if (oldMap != Map.Data()) {
-      Last += (map_ptrloc const * const) Map.Data() - (map_ptrloc const * const) oldMap;
-      I += (pkgCache::StringItem const * const) Map.Data() - (pkgCache::StringItem const * const) oldMap;
+   std::string const key(S, Size);
+
+   std::map<std::string,map_stringitem_t> * strings;
+   switch(type) {
+      case MIXED: strings = &strMixed; break;
+      case PKGNAME: strings = &strPkgNames; break;
+      case VERSIONNUMBER: strings = &strVersions; break;
+      case SECTION: strings = &strSections; break;
+      default: _error->Fatal("Unknown enum type used for string storage of '%s'", key.c_str()); return 0;
    }
    }
-   *Last = Item;
 
 
-   // Fill in the structure
-   pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
-   ItemP->NextItem = I - Cache.StringItemP;
-   ItemP->String = idxString;
+   std::map<std::string,map_stringitem_t>::const_iterator const item = strings->find(key);
+   if (item != strings->end())
+      return item->second;
 
 
-   Bucket = ItemP;
-   return ItemP->String;
+   map_stringitem_t const idxString = WriteStringInMap(S,Size);
+   strings->insert(std::make_pair(key, idxString));
+   return idxString;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // CheckValidity - Check that a cache is up-to-date			/*{{{*/
 // CheckValidity - Check that a cache is up-to-date			/*{{{*/
@@ -1275,9 +1250,9 @@ static bool CheckValidity(const string &CacheFile,
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Size is kind of an abstract notion that is only used for the progress
 /* Size is kind of an abstract notion that is only used for the progress
    meter */
    meter */
-static unsigned long ComputeSize(FileIterator Start,FileIterator End)
+static map_filesize_t ComputeSize(FileIterator Start,FileIterator End)
 {
 {
-   unsigned long TotalSize = 0;
+   map_filesize_t TotalSize = 0;
    for (; Start < End; ++Start)
    for (; Start < End; ++Start)
    {
    {
       if ((*Start)->HasPackages() == false)
       if ((*Start)->HasPackages() == false)
@@ -1292,7 +1267,7 @@ static unsigned long ComputeSize(FileIterator Start,FileIterator End)
 /* */
 /* */
 static bool BuildCache(pkgCacheGenerator &Gen,
 static bool BuildCache(pkgCacheGenerator &Gen,
 		       OpProgress *Progress,
 		       OpProgress *Progress,
-		       unsigned long &CurrentSize,unsigned long TotalSize,
+		       map_filesize_t &CurrentSize,map_filesize_t TotalSize,
 		       FileIterator Start, FileIterator End)
 		       FileIterator Start, FileIterator End)
 {
 {
    FileIterator I;
    FileIterator I;
@@ -1311,7 +1286,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
 	 continue;
 	 continue;
       }
       }
       
       
-      unsigned long Size = (*I)->Size();
+      map_filesize_t Size = (*I)->Size();
       if (Progress != NULL)
       if (Progress != NULL)
 	 Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
 	 Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
       CurrentSize += Size;
       CurrentSize += Size;
@@ -1328,7 +1303,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
       CurrentSize = 0;
       CurrentSize = 0;
       for (I = Start; I != End; ++I)
       for (I = Start; I != End; ++I)
       {
       {
-	 unsigned long Size = (*I)->Size();
+	 map_filesize_t Size = (*I)->Size();
 	 if (Progress != NULL)
 	 if (Progress != NULL)
 	    Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
 	    Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
 	 CurrentSize += Size;
 	 CurrentSize += Size;
@@ -1342,9 +1317,9 @@ static bool BuildCache(pkgCacheGenerator &Gen,
 									/*}}}*/
 									/*}}}*/
 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options	/*{{{*/
 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options	/*{{{*/
 DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) {
 DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) {
-   unsigned long const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024);
-   unsigned long const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024);
-   unsigned long const MapLimit = _config->FindI("APT::Cache-Limit", 0);
+   map_filesize_t const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024);
+   map_filesize_t const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024);
+   map_filesize_t const MapLimit = _config->FindI("APT::Cache-Limit", 0);
    Flags |= MMap::Moveable;
    Flags |= MMap::Moveable;
    if (_config->FindB("APT::Cache-Fallback", false) == true)
    if (_config->FindB("APT::Cache-Fallback", false) == true)
       Flags |= MMap::Fallback;
       Flags |= MMap::Fallback;
@@ -1382,7 +1357,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
          Files.push_back (*j);
          Files.push_back (*j);
    }
    }
    
    
-   unsigned long const EndOfSource = Files.size();
+   map_filesize_t const EndOfSource = Files.size();
    if (_system->AddStatusFiles(Files) == false)
    if (_system->AddStatusFiles(Files) == false)
       return false;
       return false;
 
 
@@ -1472,8 +1447,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
    }
    }
    
    
    // Lets try the source cache.
    // Lets try the source cache.
-   unsigned long CurrentSize = 0;
-   unsigned long TotalSize = 0;
+   map_filesize_t CurrentSize = 0;
+   map_filesize_t TotalSize = 0;
    if (CheckValidity(SrcCacheFile, List, Files.begin(),
    if (CheckValidity(SrcCacheFile, List, Files.begin(),
 		     Files.begin()+EndOfSource) == true)
 		     Files.begin()+EndOfSource) == true)
    {
    {
@@ -1481,7 +1456,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
 	 std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
 	 std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
       // Preload the map with the source cache
       // Preload the map with the source cache
       FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
       FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
-      unsigned long const alloc = Map->RawAllocate(SCacheF.Size());
+      map_pointer_t const alloc = Map->RawAllocate(SCacheF.Size());
       if ((alloc == 0 && _error->PendingError())
       if ((alloc == 0 && _error->PendingError())
 		|| SCacheF.Read((unsigned char *)Map->Data() + alloc,
 		|| SCacheF.Read((unsigned char *)Map->Data() + alloc,
 				SCacheF.Size()) == false)
 				SCacheF.Size()) == false)
@@ -1568,13 +1543,13 @@ APT_DEPRECATED bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **Ou
 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
 {
 {
    std::vector<pkgIndexFile *> Files;
    std::vector<pkgIndexFile *> Files;
-   unsigned long EndOfSource = Files.size();
+   map_filesize_t EndOfSource = Files.size();
    if (_system->AddStatusFiles(Files) == false)
    if (_system->AddStatusFiles(Files) == false)
       return false;
       return false;
 
 
    SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL);
    SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL);
-   unsigned long CurrentSize = 0;
-   unsigned long TotalSize = 0;
+   map_filesize_t CurrentSize = 0;
+   map_filesize_t TotalSize = 0;
    
    
    TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
    TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
    
    

+ 30 - 24
apt-pkg/pkgcachegen.h

@@ -27,6 +27,7 @@
 
 
 #include <vector>
 #include <vector>
 #include <string>
 #include <string>
+#include <map>
 
 
 class FileFd;
 class FileFd;
 class pkgSourceList;
 class pkgSourceList;
@@ -36,12 +37,15 @@ class pkgIndexFile;
 class pkgCacheGenerator							/*{{{*/
 class pkgCacheGenerator							/*{{{*/
 {
 {
    private:
    private:
+   APT_HIDDEN map_stringitem_t WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); };
+   APT_HIDDEN map_stringitem_t WriteStringInMap(const char *String);
+   APT_HIDDEN map_stringitem_t WriteStringInMap(const char *String, const unsigned long &Len);
+   APT_HIDDEN map_pointer_t AllocateInMap(const unsigned long &size);
 
 
-   pkgCache::StringItem *UniqHash[26];
-   APT_HIDDEN map_ptrloc WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); };
-   APT_HIDDEN map_ptrloc WriteStringInMap(const char *String);
-   APT_HIDDEN map_ptrloc WriteStringInMap(const char *String, const unsigned long &Len);
-   APT_HIDDEN map_ptrloc AllocateInMap(const unsigned long &size);
+   std::map<std::string,map_stringitem_t> strMixed;
+   std::map<std::string,map_stringitem_t> strSections;
+   std::map<std::string,map_stringitem_t> strPkgNames;
+   std::map<std::string,map_stringitem_t> strVersions;
 
 
    public:
    public:
    
    
@@ -78,21 +82,22 @@ class pkgCacheGenerator							/*{{{*/
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
 		   std::string const &Version, unsigned int const &Op,
 		   std::string const &Version, unsigned int const &Op,
-		   unsigned int const &Type, map_ptrloc* &OldDepLast);
+		   unsigned int const &Type, map_pointer_t* &OldDepLast);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
-		   map_ptrloc const Version, unsigned int const &Op,
-		   unsigned int const &Type, map_ptrloc* &OldDepLast);
-   unsigned long NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,unsigned long Next) APT_DEPRECATED
+		   map_pointer_t const Version, unsigned int const &Op,
+		   unsigned int const &Type, map_pointer_t* &OldDepLast);
+   map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,map_pointer_t const Next) APT_DEPRECATED
    { return NewVersion(Ver, VerStr, 0, 0, Next); }
    { return NewVersion(Ver, VerStr, 0, 0, Next); }
-   unsigned long NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,
-			    map_ptrloc const ParentPkg, unsigned long const Hash,
-			    unsigned long Next);
-   map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const std::string &Lang,const MD5SumValue &md5sum,map_ptrloc Next);
+   map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,
+			    map_pointer_t const ParentPkg, unsigned short const Hash,
+			    map_pointer_t const Next);
+   map_pointer_t NewDescription(pkgCache::DescIterator &Desc,const std::string &Lang,const MD5SumValue &md5sum,map_stringitem_t const idxmd5str);
 
 
    public:
    public:
 
 
-   unsigned long WriteUniqString(const char *S,unsigned int Size);
-   inline unsigned long WriteUniqString(const std::string &S) {return WriteUniqString(S.c_str(),S.length());};
+   enum StringType { MIXED, PKGNAME, VERSIONNUMBER, SECTION };
+   map_stringitem_t StoreString(StringType const type, const char * S, unsigned int const Size);
+   inline map_stringitem_t StoreString(enum StringType const type, const std::string &S) {return StoreString(type, S.c_str(),S.length());};
 
 
    void DropProgress() {Progress = 0;};
    void DropProgress() {Progress = 0;};
    bool SelectFile(const std::string &File,const std::string &Site,pkgIndexFile const &Index,
    bool SelectFile(const std::string &File,const std::string &Site,pkgIndexFile const &Index,
@@ -127,7 +132,7 @@ class pkgCacheGenerator							/*{{{*/
    APT_HIDDEN bool AddImplicitDepends(pkgCache::VerIterator &V, pkgCache::PkgIterator &D);
    APT_HIDDEN bool AddImplicitDepends(pkgCache::VerIterator &V, pkgCache::PkgIterator &D);
 
 
    APT_HIDDEN bool AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver,
    APT_HIDDEN bool AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver,
-	 std::string const &lang, MD5SumValue const &CurMd5, map_ptrloc &md5idx);
+	 std::string const &lang, MD5SumValue const &CurMd5, map_stringitem_t &md5idx);
 };
 };
 									/*}}}*/
 									/*}}}*/
 // This is the abstract package list parser class.			/*{{{*/
 // This is the abstract package list parser class.			/*{{{*/
@@ -138,17 +143,18 @@ class pkgCacheGenerator::ListParser
    
    
    // Some cache items
    // Some cache items
    pkgCache::VerIterator OldDepVer;
    pkgCache::VerIterator OldDepVer;
-   map_ptrloc *OldDepLast;
+   map_pointer_t *OldDepLast;
 
 
    // Flag file dependencies
    // Flag file dependencies
    bool FoundFileDeps;
    bool FoundFileDeps;
       
       
    protected:
    protected:
 
 
-   inline unsigned long WriteUniqString(std::string S) {return Owner->WriteUniqString(S);};
-   inline unsigned long WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);};
-   inline unsigned long WriteString(const std::string &S) {return Owner->WriteStringInMap(S);};
-   inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);};
+   inline map_stringitem_t StoreString(pkgCacheGenerator::StringType const type, std::string const &S) {return Owner->StoreString(type, S);};
+   inline map_stringitem_t StoreString(pkgCacheGenerator::StringType const type, const char *S,unsigned int Size) {return Owner->StoreString(type, S, Size);};
+
+   inline map_stringitem_t WriteString(const std::string &S) {return Owner->WriteStringInMap(S);};
+   inline map_stringitem_t WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);};
    bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch,
    bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch,
 		   const std::string &Version,unsigned int Op,
 		   const std::string &Version,unsigned int Op,
 		   unsigned int Type);
 		   unsigned int Type);
@@ -178,8 +184,8 @@ class pkgCacheGenerator::ListParser
       APT_PURE bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver);
       APT_PURE bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver);
    virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
    virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
 			   pkgCache::VerIterator &Ver) = 0;
 			   pkgCache::VerIterator &Ver) = 0;
-   virtual unsigned long Offset() = 0;
-   virtual unsigned long Size() = 0;
+   virtual map_filesize_t Offset() = 0;
+   virtual map_filesize_t Size() = 0;
    
    
    virtual bool Step() = 0;
    virtual bool Step() = 0;
    
    
@@ -187,7 +193,7 @@ class pkgCacheGenerator::ListParser
    virtual bool CollectFileProvides(pkgCache &/*Cache*/,
    virtual bool CollectFileProvides(pkgCache &/*Cache*/,
 				    pkgCache::VerIterator &/*Ver*/) {return true;};
 				    pkgCache::VerIterator &/*Ver*/) {return true;};
 
 
-   ListParser() : FoundFileDeps(false) {};
+   ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {};
    virtual ~ListParser() {};
    virtual ~ListParser() {};
 };
 };
 									/*}}}*/
 									/*}}}*/

+ 4 - 4
apt-pkg/sourcelist.cc

@@ -119,7 +119,7 @@ bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,
    std::vector<std::string> list_section = StringSplit(Section, " ");
    std::vector<std::string> list_section = StringSplit(Section, " ");
    
    
    for (std::vector<std::string>::const_iterator U = list_uris.begin();
    for (std::vector<std::string>::const_iterator U = list_uris.begin();
-        U != list_uris.end(); U++)
+        U != list_uris.end(); ++U)
    {
    {
       std::string URI = (*U);
       std::string URI = (*U);
       if (!FixupURI(URI))
       if (!FixupURI(URI))
@@ -129,10 +129,10 @@ bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,
       }
       }
 
 
       for (std::vector<std::string>::const_iterator I = list_dist.begin();
       for (std::vector<std::string>::const_iterator I = list_dist.begin();
-           I != list_dist.end(); I++)
+           I != list_dist.end(); ++I)
       {
       {
          for (std::vector<std::string>::const_iterator J = list_section.begin();
          for (std::vector<std::string>::const_iterator J = list_section.begin();
-              J != list_section.end(); J++)
+              J != list_section.end(); ++J)
          {
          {
             if (CreateItem(List, URI, (*I), (*J), Options) == false)
             if (CreateItem(List, URI, (*I), (*J), Options) == false)
             {
             {
@@ -408,7 +408,7 @@ int pkgSourceList::ParseFileDeb822(string File)
       string const types = Tags.FindS("Types");
       string const types = Tags.FindS("Types");
       std::vector<std::string> list_types = StringSplit(types, " ");
       std::vector<std::string> list_types = StringSplit(types, " ");
       for (std::vector<std::string>::const_iterator I = list_types.begin();
       for (std::vector<std::string>::const_iterator I = list_types.begin();
-        I != list_types.end(); I++)
+        I != list_types.end(); ++I)
       {
       {
          Type *Parse = Type::GetType((*I).c_str());
          Type *Parse = Type::GetType((*I).c_str());
          if (Parse == 0)
          if (Parse == 0)

+ 0 - 4
apt-pkg/sourcelist.h

@@ -96,13 +96,9 @@ class pkgSourceList : public pkgSource
    
    
    public:
    public:
 
 
-   std::vector<metaIndex *> SrcList;
-
    int ParseFileDeb822(std::string File);
    int ParseFileDeb822(std::string File);
    bool ParseFileOldStyle(std::string File);
    bool ParseFileOldStyle(std::string File);
 
 
-   public:
-
    bool ReadMainList();
    bool ReadMainList();
    bool Read(std::string File);
    bool Read(std::string File);
 
 

+ 24 - 13
apt-pkg/srcrecords.cc

@@ -81,6 +81,27 @@ bool pkgSrcRecords::Restart()
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// SrcRecords::Step - Step to the next Source Record			/*{{{*/
+// ---------------------------------------------------------------------
+/* Step to the next source package record */
+const pkgSrcRecords::Parser* pkgSrcRecords::Step()
+{
+   if (Current == Files.end())
+      return 0;
+
+   // Step to the next record, possibly switching files
+   while ((*Current)->Step() == false)
+   {
+      if (_error->PendingError() == true)
+         return 0;
+      ++Current;
+      if (Current == Files.end())
+         return 0;
+   }
+
+   return *Current;
+}
+									/*}}}*/
 // SrcRecords::Find - Find the first source package with the given name	/*{{{*/
 // SrcRecords::Find - Find the first source package with the given name	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This searches on both source package names and output binary names and
 /* This searches on both source package names and output binary names and
@@ -88,21 +109,11 @@ bool pkgSrcRecords::Restart()
    function to be called multiple times to get successive entries */
    function to be called multiple times to get successive entries */
 pkgSrcRecords::Parser *pkgSrcRecords::Find(const char *Package,bool const &SrcOnly)
 pkgSrcRecords::Parser *pkgSrcRecords::Find(const char *Package,bool const &SrcOnly)
 {
 {
-   if (Current == Files.end())
-      return 0;
-   
    while (true)
    while (true)
    {
    {
-      // Step to the next record, possibly switching files
-      while ((*Current)->Step() == false)
-      {
-	 if (_error->PendingError() == true)
-	    return 0;
-	 ++Current;
-	 if (Current == Files.end())
-	    return 0;
-      }
-      
+      if(Step() == 0)
+         return 0;
+
       // IO error somehow
       // IO error somehow
       if (_error->PendingError() == true)
       if (_error->PendingError() == true)
 	 return 0;
 	 return 0;

+ 7 - 2
apt-pkg/srcrecords.h

@@ -105,8 +105,13 @@ class pkgSrcRecords
    // Reset the search
    // Reset the search
    bool Restart();
    bool Restart();
 
 
-   // Locate a package by name
-   Parser *Find(const char *Package,bool const &SrcOnly = false);
+   // Step to the next SourcePackage and return pointer to the 
+   // next SourceRecord. The pointer is owned by libapt.
+   const Parser* Step();
+
+   // Locate a package by name and return pointer to the Parser.
+   // The pointer is owned by libapt.
+   Parser* Find(const char *Package,bool const &SrcOnly = false);
    
    
    pkgSrcRecords(pkgSourceList &List);
    pkgSrcRecords(pkgSourceList &List);
    virtual ~pkgSrcRecords();
    virtual ~pkgSrcRecords();

+ 12 - 1
apt-pkg/tagfile.cc

@@ -518,6 +518,17 @@ unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long co
    return Result;
    return Result;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// TagSection::FindB - Find boolean value                		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgTagSection::FindB(const char *Tag, bool const &Default) const
+{
+   const char *Start, *Stop;
+   if (Find(Tag, Start, Stop) == false)
+      return Default;
+   return StringToBool(string(Start, Stop));
+}
+									/*}}}*/
 // TagSection::FindFlag - Locate a yes/no type flag			/*{{{*/
 // TagSection::FindFlag - Locate a yes/no type flag			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* The bits marked in Flag are masked on/off in Flags */
 /* The bits marked in Flag are masked on/off in Flags */
@@ -590,7 +601,7 @@ static const char *iTFRewritePackageOrder[] = {
                           "Conffiles",
                           "Conffiles",
                           "Filename",
                           "Filename",
                           "Size",
                           "Size",
-                          "MD5Sum",
+                          "MD5sum",
                           "SHA1",
                           "SHA1",
                           "SHA256",
                           "SHA256",
                           "SHA512",
                           "SHA512",

+ 4 - 3
apt-pkg/tagfile.h

@@ -43,7 +43,7 @@ class pkgTagSection
       unsigned int StartValue;
       unsigned int StartValue;
       unsigned int NextInBucket;
       unsigned int NextInBucket;
 
 
-      TagData(unsigned int const StartTag) : StartTag(StartTag), NextInBucket(0) {}
+      TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {}
    };
    };
    std::vector<TagData> Tags;
    std::vector<TagData> Tags;
    unsigned int LookupTable[0x100];
    unsigned int LookupTable[0x100];
@@ -62,7 +62,8 @@ class pkgTagSection
    bool Find(const char *Tag,const char *&Start, const char *&End) const;
    bool Find(const char *Tag,const char *&Start, const char *&End) const;
    bool Find(const char *Tag,unsigned int &Pos) const;
    bool Find(const char *Tag,unsigned int &Pos) const;
    std::string FindS(const char *Tag) const;
    std::string FindS(const char *Tag) const;
-   signed int FindI(const char *Tag,signed long Default = 0) const ;
+   signed int FindI(const char *Tag,signed long Default = 0) const;
+   bool FindB(const char *Tag, bool const &Default = false) const;
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    bool FindFlag(const char *Tag,unsigned long &Flags,
    bool FindFlag(const char *Tag,unsigned long &Flags,
 		 unsigned long Flag) const;
 		 unsigned long Flag) const;
@@ -93,7 +94,7 @@ class pkgTagSection
    /** \brief amount of Tags in the current section
    /** \brief amount of Tags in the current section
     *
     *
     * Note: if a Tag is mentioned repeatly it will be counted multiple
     * Note: if a Tag is mentioned repeatly it will be counted multiple
-    * times, but only the last occurance is available via Find methods.
+    * times, but only the last occurrence is available via Find methods.
     */
     */
    unsigned int Count() const;
    unsigned int Count() const;
    bool Exists(const char* const Tag) const;
    bool Exists(const char* const Tag) const;

+ 2 - 1
apt-pkg/update.h

@@ -11,7 +11,8 @@
 #define PKGLIB_UPDATE_H
 #define PKGLIB_UPDATE_H
 
 
 class pkgAcquireStatus;
 class pkgAcquireStatus;
-
+class pkgSourceList;
+class pkgAcquire;
 
 
 bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0);
 bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0);
 bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0,
 bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0,

+ 79 - 32
apt-pkg/upgrade.cc

@@ -24,13 +24,14 @@
    
    
    The problem resolver is used to resolve the problems.
    The problem resolver is used to resolve the problems.
  */
  */
-bool pkgDistUpgrade(pkgDepCache &Cache)
+bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
 {
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    std::string const solver = _config->Find("APT::Solver", "internal");
-   if (solver != "internal") {
-      OpTextProgress Prog(*_config);
-      return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog);
-   }
+   if (solver != "internal")
+      return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, Progress);
+
+   if (Progress != NULL)
+      Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
 
 
    pkgDepCache::ActionGroup group(Cache);
    pkgDepCache::ActionGroup group(Cache);
 
 
@@ -41,12 +42,18 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
       if (I->CurrentVer != 0)
       if (I->CurrentVer != 0)
 	 Cache.MarkInstall(I, false, 0, false);
 	 Cache.MarkInstall(I, false, 0, false);
 
 
+   if (Progress != NULL)
+      Progress->Progress(10);
+
    /* Auto upgrade all installed packages, this provides the basis 
    /* Auto upgrade all installed packages, this provides the basis 
       for the installation */
       for the installation */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (I->CurrentVer != 0)
       if (I->CurrentVer != 0)
 	 Cache.MarkInstall(I, true, 0, false);
 	 Cache.MarkInstall(I, true, 0, false);
 
 
+   if (Progress != NULL)
+      Progress->Progress(50);
+
    /* Now, install each essential package which is not installed
    /* Now, install each essential package which is not installed
       (and not provided by another package in the same name group) */
       (and not provided by another package in the same name group) */
    std::string essential = _config->Find("pkgCacheGen::Essential", "all");
    std::string essential = _config->Find("pkgCacheGen::Essential", "all");
@@ -77,15 +84,24 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
       for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
 	 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 	 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 	    Cache.MarkInstall(I, true, 0, false);
 	    Cache.MarkInstall(I, true, 0, false);
-   
+
+   if (Progress != NULL)
+      Progress->Progress(55);
+
    /* We do it again over all previously installed packages to force 
    /* We do it again over all previously installed packages to force 
       conflict resolution on them all. */
       conflict resolution on them all. */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (I->CurrentVer != 0)
       if (I->CurrentVer != 0)
 	 Cache.MarkInstall(I, false, 0, false);
 	 Cache.MarkInstall(I, false, 0, false);
 
 
+   if (Progress != NULL)
+      Progress->Progress(65);
+
    pkgProblemResolver Fix(&Cache);
    pkgProblemResolver Fix(&Cache);
 
 
+   if (Progress != NULL)
+      Progress->Progress(95);
+
    // Hold back held packages.
    // Hold back held packages.
    if (_config->FindB("APT::Ignore-Hold",false) == false)
    if (_config->FindB("APT::Ignore-Hold",false) == false)
    {
    {
@@ -98,18 +114,22 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
 	 }
 	 }
       }
       }
    }
    }
-   
-   return Fix.Resolve();
+
+   bool const success = Fix.Resolve(false, Progress);
+   if (Progress != NULL)
+      Progress->Done();
+   return success;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs        /*{{{*/
 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs        /*{{{*/
-static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
+static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
 {
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    std::string const solver = _config->Find("APT::Solver", "internal");
-   if (solver != "internal") {
-      OpTextProgress Prog(*_config);
-      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
-   }
+   if (solver != "internal")
+      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
+
+   if (Progress != NULL)
+      Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
 
 
    pkgDepCache::ActionGroup group(Cache);
    pkgDepCache::ActionGroup group(Cache);
 
 
@@ -131,8 +151,15 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
 	 Cache.MarkInstall(I, false, 0, false);
 	 Cache.MarkInstall(I, false, 0, false);
    }
    }
-      
-   return Fix.ResolveByKeep();
+
+   if (Progress != NULL)
+      Progress->Progress(50);
+
+   // resolve remaining issues via keep
+   bool const success = Fix.ResolveByKeep(Progress);
+   if (Progress != NULL)
+      Progress->Done();
+   return success;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/
 // AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/
@@ -141,8 +168,15 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
  * Upgrade as much as possible without deleting anything (useful for
  * Upgrade as much as possible without deleting anything (useful for
  * stable systems)
  * stable systems)
  */
  */
-static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
+static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
 {
 {
+   std::string const solver = _config->Find("APT::Solver", "internal");
+   if (solver != "internal")
+      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
+
+   if (Progress != NULL)
+      Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
+
    pkgDepCache::ActionGroup group(Cache);
    pkgDepCache::ActionGroup group(Cache);
 
 
    pkgProblemResolver Fix(&Cache);
    pkgProblemResolver Fix(&Cache);
@@ -164,18 +198,30 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
       }
       }
    }
    }
 
 
+   if (Progress != NULL)
+      Progress->Progress(10);
+
    // then let auto-install loose
    // then let auto-install loose
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (Cache[I].Install())
       if (Cache[I].Install())
 	 Cache.MarkInstall(I, true, 0, false);
 	 Cache.MarkInstall(I, true, 0, false);
 
 
+   if (Progress != NULL)
+      Progress->Progress(50);
+
    // ... but it may remove stuff, we we need to clean up afterwards again
    // ... but it may remove stuff, we we need to clean up afterwards again
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (Cache[I].Delete() == true)
       if (Cache[I].Delete() == true)
 	 Cache.MarkKeep(I, false, false);
 	 Cache.MarkKeep(I, false, false);
 
 
+   if (Progress != NULL)
+      Progress->Progress(60);
+
    // resolve remaining issues via keep
    // resolve remaining issues via keep
-   return Fix.ResolveByKeep();
+   bool const success = Fix.ResolveByKeep(Progress);
+   if (Progress != NULL)
+      Progress->Done();
+   return success;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // AllUpgrade - Upgrade as many packages as possible			/*{{{*/
 // AllUpgrade - Upgrade as many packages as possible			/*{{{*/
@@ -183,9 +229,9 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
 /* Right now the system must be consistent before this can be called.
 /* Right now the system must be consistent before this can be called.
    It also will not change packages marked for install, it only tries
    It also will not change packages marked for install, it only tries
    to install packages not marked for install */
    to install packages not marked for install */
-bool pkgAllUpgrade(pkgDepCache &Cache)
+bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
 {
 {
-   return pkgAllUpgradeNoNewPackages(Cache);
+   return pkgAllUpgradeNoNewPackages(Cache, Progress);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // MinimizeUpgrade - Minimizes the set of packages to be upgraded	/*{{{*/
 // MinimizeUpgrade - Minimizes the set of packages to be upgraded	/*{{{*/
@@ -233,24 +279,25 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// APT::Upgrade::Upgrade - Upgrade using a specific strategy     	/*{{{*/
-bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode)
+// APT::Upgrade::Upgrade - Upgrade using a specific strategy		/*{{{*/
+bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress)
 {
 {
-   if (mode == 0) 
-   {
-      return pkgDistUpgrade(Cache);
-   }
+#if __GNUC__ >= 4
+	// the deprecated methods will become our privates, so that is fine
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+   if (mode == ALLOW_EVERYTHING)
+      return pkgDistUpgrade(Cache, Progress);
    else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
    else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
-   {
-      return pkgAllUpgradeWithNewPackages(Cache);
-   } 
+      return pkgAllUpgradeWithNewPackages(Cache, Progress);
    else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
    else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
-   {
-      return pkgAllUpgradeNoNewPackages(Cache);
-   }
+      return pkgAllUpgradeNoNewPackages(Cache, Progress);
    else
    else
       _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
       _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
-
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
    return false;
    return false;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 9 - 5
apt-pkg/upgrade.h

@@ -10,23 +10,27 @@
 #ifndef PKGLIB_UPGRADE_H
 #ifndef PKGLIB_UPGRADE_H
 #define PKGLIB_UPGRADE_H
 #define PKGLIB_UPGRADE_H
 
 
+#include <stddef.h>
+#include <apt-pkg/macros.h>
+
 class pkgDepCache;
 class pkgDepCache;
+class OpProgress;
 
 
 namespace APT {
 namespace APT {
    namespace Upgrade {
    namespace Upgrade {
       // FIXME: make this "enum class UpgradeMode {" once we enable c++11
       // FIXME: make this "enum class UpgradeMode {" once we enable c++11
       enum UpgradeMode {
       enum UpgradeMode {
+	 ALLOW_EVERYTHING = 0,
          FORBID_REMOVE_PACKAGES = 1,
          FORBID_REMOVE_PACKAGES = 1,
          FORBID_INSTALL_NEW_PACKAGES = 2
          FORBID_INSTALL_NEW_PACKAGES = 2
       };
       };
-      bool Upgrade(pkgDepCache &Cache, int UpgradeMode);
+      bool Upgrade(pkgDepCache &Cache, int UpgradeMode, OpProgress * const Progress = NULL);
    }
    }
 }
 }
 
 
 // please use APT::Upgrade::Upgrade() instead
 // please use APT::Upgrade::Upgrade() instead
-bool pkgDistUpgrade(pkgDepCache &Cache);
-bool pkgAllUpgrade(pkgDepCache &Cache);
-bool pkgMinimizeUpgrade(pkgDepCache &Cache);
-
+APT_DEPRECATED bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress = NULL);
+APT_DEPRECATED bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress = NULL);
 
 
+bool pkgMinimizeUpgrade(pkgDepCache &Cache);
 #endif
 #endif

+ 2 - 2
apt-private/acqprogress.cc

@@ -202,9 +202,9 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner)
       S += strlen(S);
       S += strlen(S);
 
 
       // Show the short mode string
       // Show the short mode string
-      if (I->CurrentItem->Owner->Mode != 0)
+      if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false)
       {
       {
-	 snprintf(S,End-S," %s",I->CurrentItem->Owner->Mode);
+	 snprintf(S,End-S, " %s", I->CurrentItem->Owner->ActiveSubprocess.c_str());
 	 S += strlen(S);
 	 S += strlen(S);
       }
       }
 
 

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

@@ -32,8 +32,10 @@ int CacheFile::NameComp(const void *a,const void *b)
    
    
    const pkgCache::Package &A = **(pkgCache::Package **)a;
    const pkgCache::Package &A = **(pkgCache::Package **)a;
    const pkgCache::Package &B = **(pkgCache::Package **)b;
    const pkgCache::Package &B = **(pkgCache::Package **)b;
+   const pkgCache::Group * const GA = SortCache->GrpP + A.Group;
+   const pkgCache::Group * const GB = SortCache->GrpP + B.Group;
 
 
-   return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
+   return strcmp(SortCache->StrP + GA->Name,SortCache->StrP + GB->Name);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // CacheFile::Sort - Sort by name					/*{{{*/
 // CacheFile::Sort - Sort by name					/*{{{*/

+ 46 - 43
apt-private/private-cacheset.cc

@@ -14,74 +14,77 @@
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 
 
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                 LocalitySortedVersionSet &output_set,
-                                 OpProgress &progress)
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                 APT::VersionContainerInterface * const vci,
+                                 OpProgress * const progress)
 {
 {
     Matcher null_matcher = Matcher();
     Matcher null_matcher = Matcher();
-    return GetLocalitySortedVersionSet(CacheFile, output_set, 
+    return GetLocalitySortedVersionSet(CacheFile, vci,
                                        null_matcher, progress);
                                        null_matcher, progress);
 }
 }
 
 
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                 LocalitySortedVersionSet &output_set,
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                 APT::VersionContainerInterface * const vci,
                                  Matcher &matcher,
                                  Matcher &matcher,
-                                 OpProgress &progress)
+                                 OpProgress * const progress)
 {
 {
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgDepCache *DepCache = CacheFile.GetDepCache();
    pkgDepCache *DepCache = CacheFile.GetDepCache();
+   APT::CacheSetHelper helper(false);
 
 
    int Done=0;
    int Done=0;
-   progress.SubProgress(Cache->Head().PackageCount, _("Sorting"));
+   if (progress != NULL)
+      progress->SubProgress(Cache->Head().PackageCount, _("Sorting"));
+
+   bool const insertCurrentVer = _config->FindB("APT::Cmd::Installed", false);
+   bool const insertUpgradable = _config->FindB("APT::Cmd::Upgradable", false);
+   bool const insertManualInstalled = _config->FindB("APT::Cmd::Manual-Installed", false);
+
    for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
    for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
    {
    {
-      if (Done%500 == 0)
-         progress.Progress(Done);
-      Done++;
+      if (progress != NULL)
+      {
+	 if (Done % 500 == 0)
+	    progress->Progress(Done);
+	 ++Done;
+      }
+
+      // exclude virtual pkgs
+      if (P->VersionList == 0)
+	 continue;
 
 
       if ((matcher)(P) == false)
       if ((matcher)(P) == false)
-         continue;
+	 continue;
 
 
-      // exclude virtual pkgs
-      if (P.VersionList() == 0)
-         continue;
       pkgDepCache::StateCache &state = (*DepCache)[P];
       pkgDepCache::StateCache &state = (*DepCache)[P];
-      if (_config->FindB("APT::Cmd::Installed") == true)
+      if (insertCurrentVer == true)
       {
       {
-         if (P.CurrentVer() != NULL)
-         {
-            output_set.insert(P.CurrentVer());
-         }
+	 if (P->CurrentVer != 0)
+	    vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::INSTALLED, helper);
       }
       }
-      else if (_config->FindB("APT::Cmd::Upgradable") == true)
+      else if (insertUpgradable == true)
       {
       {
-         if(P.CurrentVer() && state.Upgradable())
-         {
-             pkgPolicy *policy = CacheFile.GetPolicy();
-             output_set.insert(policy->GetCandidateVer(P));
-         }
+	 if(P.CurrentVer() && state.Upgradable())
+	    vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::CANDIDATE, helper);
       }
       }
-      else if (_config->FindB("APT::Cmd::Manual-Installed") == true)
+      else if (insertManualInstalled == true)
       {
       {
-         if (P.CurrentVer() && 
-             ((*DepCache)[P].Flags & pkgCache::Flag::Auto) == false)
-         {
-             pkgPolicy *policy = CacheFile.GetPolicy();
-             output_set.insert(policy->GetCandidateVer(P));
-         }
+	 if (P.CurrentVer() &&
+	       ((*DepCache)[P].Flags & pkgCache::Flag::Auto) == false)
+	    vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::CANDIDATE, helper);
       }
       }
-      else 
+      else
       {
       {
-         pkgPolicy *policy = CacheFile.GetPolicy();
-         if (policy->GetCandidateVer(P).IsGood())
-            output_set.insert(policy->GetCandidateVer(P));
-         else 
-            // no candidate, this may happen for packages in 
-            // dpkg "deinstall ok config-file" state - we pick the first ver
-            // (which should be the only one)
-            output_set.insert(P.VersionList());
+         if (vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::CANDIDATE, helper) == false)
+	 {
+	    // no candidate, this may happen for packages in
+	    // dpkg "deinstall ok config-file" state - we pick the first ver
+	    // (which should be the only one)
+	    vci->insert(P.VersionList());
+	 }
       }
       }
    }
    }
-   progress.Done();
+   if (progress != NULL)
+      progress->Done();
    return true;
    return true;
 }
 }

+ 17 - 20
apt-private/private-cacheset.h

@@ -62,13 +62,13 @@ public:
 };
 };
 
 
 // FIXME: add default argument for OpProgress (or overloaded function)
 // FIXME: add default argument for OpProgress (or overloaded function)
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                    LocalitySortedVersionSet &output_set,
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                    APT::VersionContainerInterface * const vci,
                                     Matcher &matcher,
                                     Matcher &matcher,
-                                    OpProgress &progress);
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                    LocalitySortedVersionSet &output_set,
-                                    OpProgress &progress);
+                                    OpProgress * const progress);
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                    APT::VersionContainerInterface * const vci,
+                                    OpProgress * const progress);
 
 
 
 
 // CacheSetHelper saving virtual packages				/*{{{*/
 // CacheSetHelper saving virtual packages				/*{{{*/
@@ -76,19 +76,16 @@ class CacheSetHelperVirtuals: public APT::CacheSetHelper {
 public:
 public:
    APT::PackageSet virtualPkgs;
    APT::PackageSet virtualPkgs;
 
 
-   virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
-      virtualPkgs.insert(Pkg);
-      return CacheSetHelper::canNotFindCandidateVer(Cache, Pkg);
+   virtual pkgCache::VerIterator canNotGetVersion(enum CacheSetHelper::VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+      if (select == NEWEST || select == CANDIDATE || select == ALL)
+	 virtualPkgs.insert(Pkg);
+      return CacheSetHelper::canNotGetVersion(select, Cache, Pkg);
    }
    }
 
 
-   virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
-      virtualPkgs.insert(Pkg);
-      return CacheSetHelper::canNotFindNewestVer(Cache, Pkg);
-   }
-
-   virtual void canNotFindAllVer(APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
-      virtualPkgs.insert(Pkg);
-      CacheSetHelper::canNotFindAllVer(vci, Cache, Pkg);
+   virtual void canNotFindVersion(enum CacheSetHelper::VerSelector const select, APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+      if (select == NEWEST || select == CANDIDATE || select == ALL)
+	 virtualPkgs.insert(Pkg);
+      return CacheSetHelper::canNotFindVersion(select, vci, Cache, Pkg);
    }
    }
 
 
    CacheSetHelperVirtuals(bool const ShowErrors = true, GlobalError::MsgType const &ErrorType = GlobalError::NOTICE) : CacheSetHelper(ShowErrors, ErrorType) {}
    CacheSetHelperVirtuals(bool const ShowErrors = true, GlobalError::MsgType const &ErrorType = GlobalError::NOTICE) : CacheSetHelper(ShowErrors, ErrorType) {}
@@ -190,7 +187,7 @@ public:
 	}
 	}
 
 
 	virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
 	virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
-		APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
+		APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, CacheSetHelper::CANDIDATE);
 		if (verset.empty() == false)
 		if (verset.empty() == false)
 			return *(verset.begin());
 			return *(verset.begin());
 		else if (ShowError == true) {
 		else if (ShowError == true) {
@@ -203,7 +200,7 @@ public:
 	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
 	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
 		if (Pkg->ProvidesList != 0)
 		if (Pkg->ProvidesList != 0)
 		{
 		{
-			APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+			APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, CacheSetHelper::NEWEST);
 			if (verset.empty() == false)
 			if (verset.empty() == false)
 				return *(verset.begin());
 				return *(verset.begin());
 			if (ShowError == true)
 			if (ShowError == true)
@@ -231,7 +228,7 @@ public:
 	}
 	}
 
 
 	APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
 	APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
-						APT::VersionSet::Version const &select) {
+						CacheSetHelper::VerSelector const select) {
 		/* This is a pure virtual package and there is a single available
 		/* This is a pure virtual package and there is a single available
 		   candidate providing it. */
 		   candidate providing it. */
 		if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
 		if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)

+ 7 - 2
apt-private/private-cmndline.cc

@@ -70,6 +70,8 @@ static bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char cons
    else
    else
       return false;
       return false;
 
 
+   bool const found_something = Args.empty() == false;
+
    // FIXME: move to the correct command(s)
    // FIXME: move to the correct command(s)
    addArg('g', "generate", "APT::Cache::Generate", 0);
    addArg('g', "generate", "APT::Cache::Generate", 0);
    addArg('t', "target-release", "APT::Default-Release", CommandLine::HasArg);
    addArg('t', "target-release", "APT::Default-Release", CommandLine::HasArg);
@@ -77,7 +79,8 @@ static bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char cons
 
 
    addArg('p', "pkg-cache", "Dir::Cache::pkgcache", CommandLine::HasArg);
    addArg('p', "pkg-cache", "Dir::Cache::pkgcache", CommandLine::HasArg);
    addArg('s', "src-cache", "Dir::Cache::srcpkgcache", CommandLine::HasArg);
    addArg('s', "src-cache", "Dir::Cache::srcpkgcache", CommandLine::HasArg);
-   return true;
+
+   return found_something;
 }
 }
 									/*}}}*/
 									/*}}}*/
 static bool addArgumentsAPTCDROM(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
 static bool addArgumentsAPTCDROM(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
@@ -172,6 +175,8 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
       addArg('s', "no-act", "APT::Get::Simulate", 0);
       addArg('s', "no-act", "APT::Get::Simulate", 0);
    }
    }
 
 
+   bool const found_something = Args.empty() == false;
+
    // FIXME: move to the correct command(s)
    // FIXME: move to the correct command(s)
    addArg('d',"download-only","APT::Get::Download-Only",0);
    addArg('d',"download-only","APT::Get::Download-Only",0);
    addArg('y',"yes","APT::Get::Assume-Yes",0);
    addArg('y',"yes","APT::Get::Assume-Yes",0);
@@ -197,7 +202,7 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
    addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean);
    addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean);
    addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0);
    addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0);
 
 
-   return true;
+   return found_something;
 }
 }
 									/*}}}*/
 									/*}}}*/
 static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
 static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/

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

@@ -28,6 +28,11 @@ bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser)
    if (UntrustedList == "")
    if (UntrustedList == "")
       return true;
       return true;
 
 
+   return AuthPrompt(UntrustedList, PromptUser);
+}
+
+bool AuthPrompt(std::string UntrustedList, bool const PromptUser)
+{
    ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
    ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
 
 
    if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
    if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)

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

@@ -5,7 +5,13 @@
 
 
 class pkgAcquire;
 class pkgAcquire;
 
 
+// Check if all files in the fetcher are authenticated
 APT_PUBLIC bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser);
 APT_PUBLIC bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser);
+
+// show a authentication warning prompt and return true if the system
+// should continue
+APT_PUBLIC bool AuthPrompt(std::string UntrustedList, bool const PromptUser);
+
 APT_PUBLIC bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure);
 APT_PUBLIC bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure);
 
 
 #endif
 #endif

+ 159 - 9
apt-private/private-install.cc

@@ -19,7 +19,7 @@
 #include <apt-pkg/macros.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
-#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/upgrade.h>
 #include <apt-pkg/install-progress.h>
 #include <apt-pkg/install-progress.h>
 
 
 #include <errno.h>
 #include <errno.h>
@@ -527,15 +527,14 @@ static bool DoAutomaticRemove(CacheFile &Cache)
 static const unsigned short MOD_REMOVE = 1;
 static const unsigned short MOD_REMOVE = 1;
 static const unsigned short MOD_INSTALL = 2;
 static const unsigned short MOD_INSTALL = 2;
 
 
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
 {
 {
    std::map<unsigned short, APT::VersionSet> verset;
    std::map<unsigned short, APT::VersionSet> verset;
-   return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
+   return DoCacheManipulationFromCommandLine(CmdL, Cache, verset, UpgradeMode);
 }
 }
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
-                                        std::map<unsigned short, APT::VersionSet> &verset)
+                                        std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
 {
 {
-
    // Enter the special broken fixing mode if the user specified arguments
    // Enter the special broken fixing mode if the user specified arguments
    bool BrokenFix = false;
    bool BrokenFix = false;
    if (Cache->BrokenCount() != 0)
    if (Cache->BrokenCount() != 0)
@@ -561,9 +560,9 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
 
 
    std::list<APT::VersionSet::Modifier> mods;
    std::list<APT::VersionSet::Modifier> mods;
    mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
    mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
-		APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
+		APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::CANDIDATE));
    mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
    mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
-		APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
+		APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::NEWEST));
    CacheSetHelperAPTGet helper(c0out);
    CacheSetHelperAPTGet helper(c0out);
    verset = APT::VersionSet::GroupedFromCommandLine(Cache,
    verset = APT::VersionSet::GroupedFromCommandLine(Cache,
 		CmdL.FileList + 1, mods, fallback, helper);
 		CmdL.FileList + 1, mods, fallback, helper);
@@ -620,7 +619,17 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
       if (Fix != NULL)
       if (Fix != NULL)
       {
       {
 	 // Call the scored problem resolver
 	 // Call the scored problem resolver
-	 Fix->Resolve(true);
+	 OpTextProgress Progress(*_config);
+	 bool const distUpgradeMode = strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0;
+
+	 bool resolver_fail = false;
+	 if (distUpgradeMode == true || UpgradeMode != APT::Upgrade::ALLOW_EVERYTHING)
+	    resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode, &Progress);
+	 else
+	    resolver_fail = Fix->Resolve(true, &Progress);
+
+	 if (resolver_fail == false && Cache->BrokenCount() == 0)
+	    return false;
       }
       }
 
 
       // Now we check the state of the packages,
       // Now we check the state of the packages,
@@ -702,7 +711,7 @@ bool DoInstall(CommandLine &CmdL)
    
    
    std::map<unsigned short, APT::VersionSet> verset;
    std::map<unsigned short, APT::VersionSet> verset;
 
 
-   if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
+   if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset, 0))
       return false;
       return false;
 
 
    /* Print out a list of packages that are going to be installed extra
    /* Print out a list of packages that are going to be installed extra
@@ -828,3 +837,144 @@ bool DoInstall(CommandLine &CmdL)
    return InstallPackages(Cache,false);   
    return InstallPackages(Cache,false);   
 }
 }
 									/*}}}*/
 									/*}}}*/
+
+// TryToInstall - Mark a package for installation			/*{{{*/
+void TryToInstall::operator() (pkgCache::VerIterator const &Ver) {
+   pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+   Cache->GetDepCache()->SetCandidateVersion(Ver);
+   pkgDepCache::StateCache &State = (*Cache)[Pkg];
+
+   // Handle the no-upgrade case
+   if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
+      ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+	    Pkg.FullName(true).c_str());
+   // Ignore request for install if package would be new
+   else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
+      ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
+	    Pkg.FullName(true).c_str());
+   else {
+      if (Fix != NULL) {
+	 Fix->Clear(Pkg);
+	 Fix->Protect(Pkg);
+      }
+      Cache->GetDepCache()->MarkInstall(Pkg,false);
+
+      if (State.Install() == false) {
+	 if (_config->FindB("APT::Get::ReInstall",false) == true) {
+	    if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+	       ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
+		     Pkg.FullName(true).c_str());
+	    else
+	       Cache->GetDepCache()->SetReInstall(Pkg, true);
+	 } else
+	    ioprintf(c1out,_("%s is already the newest version.\n"),
+		  Pkg.FullName(true).c_str());
+      }
+
+      // Install it with autoinstalling enabled (if we not respect the minial
+      // required deps or the policy)
+      if (FixBroken == false)
+	 doAutoInstallLater.insert(Pkg);
+   }
+
+   // see if we need to fix the auto-mark flag
+   // e.g. apt-get install foo
+   // where foo is marked automatic
+   if (State.Install() == false &&
+	 (State.Flags & pkgCache::Flag::Auto) &&
+	 _config->FindB("APT::Get::ReInstall",false) == false &&
+	 _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+	 _config->FindB("APT::Get::Download-Only",false) == false)
+   {
+      ioprintf(c1out,_("%s set to manually installed.\n"),
+	    Pkg.FullName(true).c_str());
+      Cache->GetDepCache()->MarkAuto(Pkg,false);
+      AutoMarkChanged++;
+   }
+}
+									/*}}}*/
+bool TryToInstall::propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > const &start, std::ostream &out)/*{{{*/
+{
+   for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
+	 s != start.end(); ++s)
+      Cache->GetDepCache()->SetCandidateVersion(s->first);
+
+   bool Success = true;
+   // the Changed list contains:
+   //   first: "new version"
+   //   second: "what-caused the change"
+   std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
+   for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
+	 s != start.end(); ++s)
+   {
+      Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
+      // We continue here even if it failed to enhance the ShowBroken output
+      Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
+   }
+   for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
+	 c != Changed.end(); ++c)
+   {
+      if (c->second.end() == true)
+	 ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+	       c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
+      else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
+      {
+	 pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
+	 ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
+	       V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
+      }
+   }
+   return Success;
+}
+									/*}}}*/
+void TryToInstall::doAutoInstall() {					/*{{{*/
+   for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
+	 P != doAutoInstallLater.end(); ++P) {
+      pkgDepCache::StateCache &State = (*Cache)[P];
+      if (State.InstBroken() == false && State.InstPolicyBroken() == false)
+	 continue;
+      Cache->GetDepCache()->MarkInstall(P, true);
+   }
+   doAutoInstallLater.clear();
+}
+									/*}}}*/
+// TryToRemove - Mark a package for removal				/*{{{*/
+void TryToRemove::operator() (pkgCache::VerIterator const &Ver)
+{
+   pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+   if (Fix != NULL)
+   {
+      Fix->Clear(Pkg);
+      Fix->Protect(Pkg);
+      Fix->Remove(Pkg);
+   }
+
+   if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
+	 (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
+   {
+      pkgCache::GrpIterator Grp = Pkg.Group();
+      pkgCache::PkgIterator P = Grp.PackageList();
+      for (; P.end() != true; P = Grp.NextPkg(P))
+      {
+	 if (P == Pkg)
+	    continue;
+	 if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
+	 {
+	    // TRANSLATORS: Note, this is not an interactive question
+	    ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
+		  Pkg.FullName(true).c_str(), P.FullName(true).c_str());
+	    break;
+	 }
+      }
+      if (P.end() == true)
+	 ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+
+      // MarkInstall refuses to install packages on hold
+      Pkg->SelectedState = pkgCache::State::Hold;
+   }
+   else
+      Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
+}
+									/*}}}*/

+ 9 - 151
apt-private/private-install.h

@@ -3,43 +3,33 @@
 
 
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
-#include <apt-pkg/depcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/cacheset.h>
 #include <apt-pkg/cacheset.h>
-#include <apt-pkg/strutl.h>
-#include <apt-pkg/algorithms.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/macros.h>
 
 
-#include <apt-private/private-output.h>
-
-#include <stddef.h>
-#include <iosfwd>
 #include <list>
 #include <list>
-#include <map>
 #include <string>
 #include <string>
 #include <utility>
 #include <utility>
 
 
-
-#include <apti18n.h>
-
 class CacheFile;
 class CacheFile;
 class CommandLine;
 class CommandLine;
+class pkgProblemResolver;
 
 
 #define RAMFS_MAGIC     0x858458f6
 #define RAMFS_MAGIC     0x858458f6
 
 
 APT_PUBLIC bool DoInstall(CommandLine &Cmd);
 APT_PUBLIC bool DoInstall(CommandLine &Cmd);
 
 
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
-                                        std::map<unsigned short, APT::VersionSet> &verset);
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache);
+                                        std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode);
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode);
 
 
 APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
 APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
                         bool Safety = true);
                         bool Safety = true);
 
 
 
 
 // TryToInstall - Mark a package for installation			/*{{{*/
 // TryToInstall - Mark a package for installation			/*{{{*/
-struct TryToInstall {
+struct APT_PUBLIC TryToInstall {
    pkgCacheFile* Cache;
    pkgCacheFile* Cache;
    pkgProblemResolver* Fix;
    pkgProblemResolver* Fix;
    bool FixBroken;
    bool FixBroken;
@@ -49,109 +39,13 @@ struct TryToInstall {
    TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM),
    TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM),
 			FixBroken(FixBroken), AutoMarkChanged(0) {};
 			FixBroken(FixBroken), AutoMarkChanged(0) {};
 
 
-   void operator() (pkgCache::VerIterator const &Ver) {
-      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-
-      Cache->GetDepCache()->SetCandidateVersion(Ver);
-      pkgDepCache::StateCache &State = (*Cache)[Pkg];
-
-      // Handle the no-upgrade case
-      if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
-	 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
-		  Pkg.FullName(true).c_str());
-      // Ignore request for install if package would be new
-      else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
-	 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
-		  Pkg.FullName(true).c_str());
-      else {
-	 if (Fix != NULL) {
-	    Fix->Clear(Pkg);
-	    Fix->Protect(Pkg);
-	 }
-	 Cache->GetDepCache()->MarkInstall(Pkg,false);
-
-	 if (State.Install() == false) {
-	    if (_config->FindB("APT::Get::ReInstall",false) == true) {
-	       if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
-		  ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
-			   Pkg.FullName(true).c_str());
-	       else
-		  Cache->GetDepCache()->SetReInstall(Pkg, true);
-	    } else
-	       ioprintf(c1out,_("%s is already the newest version.\n"),
-			Pkg.FullName(true).c_str());
-	 }
-
-	 // Install it with autoinstalling enabled (if we not respect the minial
-	 // required deps or the policy)
-	 if (FixBroken == false)
-	    doAutoInstallLater.insert(Pkg);
-      }
-
-      // see if we need to fix the auto-mark flag
-      // e.g. apt-get install foo
-      // where foo is marked automatic
-      if (State.Install() == false &&
-	  (State.Flags & pkgCache::Flag::Auto) &&
-	  _config->FindB("APT::Get::ReInstall",false) == false &&
-	  _config->FindB("APT::Get::Only-Upgrade",false) == false &&
-	  _config->FindB("APT::Get::Download-Only",false) == false)
-      {
-	 ioprintf(c1out,_("%s set to manually installed.\n"),
-		  Pkg.FullName(true).c_str());
-	 Cache->GetDepCache()->MarkAuto(Pkg,false);
-	 AutoMarkChanged++;
-      }
-   }
-
-   bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > start, std::ostream &out)
-   {
-      for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
-		s != start.end(); ++s)
-	 Cache->GetDepCache()->SetCandidateVersion(s->first);
-
-      bool Success = true;
-      // the Changed list contains:
-      //   first: "new version" 
-      //   second: "what-caused the change" 
-      std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
-      for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
-		s != start.end(); ++s)
-      {
-	 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
-	 // We continue here even if it failed to enhance the ShowBroken output
-	 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
-      }
-      for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
-	   c != Changed.end(); ++c)
-      {
-	 if (c->second.end() == true)
-	    ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
-		     c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
-	 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
-	 {
-	    pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
-	    ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
-		     V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
-	 }
-      }
-      return Success;
-   }
-
-   void doAutoInstall() {
-      for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
-	   P != doAutoInstallLater.end(); ++P) {
-	 pkgDepCache::StateCache &State = (*Cache)[P];
-	 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
-	    continue;
-	 Cache->GetDepCache()->MarkInstall(P, true);
-      }
-      doAutoInstallLater.clear();
-   }
+   void operator() (pkgCache::VerIterator const &Ver);
+   bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > const &start, std::ostream &out);
+   void doAutoInstall();
 };
 };
 									/*}}}*/
 									/*}}}*/
 // TryToRemove - Mark a package for removal				/*{{{*/
 // TryToRemove - Mark a package for removal				/*{{{*/
-struct TryToRemove {
+struct APT_PUBLIC TryToRemove {
    pkgCacheFile* Cache;
    pkgCacheFile* Cache;
    pkgProblemResolver* Fix;
    pkgProblemResolver* Fix;
    bool PurgePkgs;
    bool PurgePkgs;
@@ -159,43 +53,7 @@ struct TryToRemove {
    TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM),
    TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM),
 				PurgePkgs(_config->FindB("APT::Get::Purge", false)) {};
 				PurgePkgs(_config->FindB("APT::Get::Purge", false)) {};
 
 
-   void operator() (pkgCache::VerIterator const &Ver)
-   {
-      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-
-      if (Fix != NULL)
-      {
-	 Fix->Clear(Pkg);
-	 Fix->Protect(Pkg);
-	 Fix->Remove(Pkg);
-      }
-
-      if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
-	  (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
-      {
-	 pkgCache::GrpIterator Grp = Pkg.Group();
-	 pkgCache::PkgIterator P = Grp.PackageList();
-	 for (; P.end() != true; P = Grp.NextPkg(P))
-	 {
-	    if (P == Pkg)
-	       continue;
-	    if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
-	    {
-	       // TRANSLATORS: Note, this is not an interactive question
-	       ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
-			Pkg.FullName(true).c_str(), P.FullName(true).c_str());
-	       break;
-	    }
-	 }
-	 if (P.end() == true)
-	    ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
-
-	 // MarkInstall refuses to install packages on hold
-	 Pkg->SelectedState = pkgCache::State::Hold;
-      }
-      else
-	 Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
-   }
+   void operator() (pkgCache::VerIterator const &Ver);
 };
 };
 									/*}}}*/
 									/*}}}*/
 
 

+ 18 - 23
apt-private/private-list.cc

@@ -77,15 +77,14 @@ private:
 };
 };
 									/*}}}*/
 									/*}}}*/
 static void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records,/*{{{*/
 static void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records,/*{{{*/
-                     pkgCache::PkgIterator P,    
-                     std::ostream &outs,
-                     bool include_summary=true)
+                     pkgCache::PkgIterator const &P, std::ostream &outs,
+                     std::string const &format)
 {
 {
    for (pkgCache::VerIterator Ver = P.VersionList();
    for (pkgCache::VerIterator Ver = P.VersionList();
         Ver.end() == false; ++Ver)
         Ver.end() == false; ++Ver)
    {
    {
-      ListSingleVersion(CacheFile, records, Ver, outs, include_summary);
-      outs << "\n";
+      ListSingleVersion(CacheFile, records, Ver, outs, format);
+      outs << std::endl;
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -109,10 +108,9 @@ bool DoList(CommandLine &Cmd)
       patterns = Cmd.FileList + 1;
       patterns = Cmd.FileList + 1;
    }
    }
 
 
-   std::map<std::string, std::string> output_map;
-   std::map<std::string, std::string>::const_iterator K;
-
-   bool includeSummary = _config->FindB("APT::Cmd::List-Include-Summary");
+   std::string format = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture}${ }${apt:Status}";
+   if (_config->FindB("APT::Cmd::List-Include-Summary", false) == true)
+      format += "\n  ${Description}\n";
 
 
    PackageNameMatcher matcher(patterns);
    PackageNameMatcher matcher(patterns);
    LocalitySortedVersionSet bag;
    LocalitySortedVersionSet bag;
@@ -121,37 +119,34 @@ bool DoList(CommandLine &Cmd)
                             Cache->Head().PackageCount, 
                             Cache->Head().PackageCount, 
                             Cache->Head().PackageCount,
                             Cache->Head().PackageCount,
                             _("Listing"));
                             _("Listing"));
-   GetLocalitySortedVersionSet(CacheFile, bag, matcher, progress);
-   bool ShowAllVersions = _config->FindB("APT::Cmd::All-Versions", false);
+   GetLocalitySortedVersionSet(CacheFile, &bag, matcher, &progress);
+   bool const ShowAllVersions = _config->FindB("APT::Cmd::All-Versions", false);
+   std::map<std::string, std::string> output_map;
    for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); ++V)
    for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); ++V)
    {
    {
       std::stringstream outs;
       std::stringstream outs;
       if(ShowAllVersions == true)
       if(ShowAllVersions == true)
-      {
-         ListAllVersions(CacheFile, records, V.ParentPkg(), outs, includeSummary);
-         output_map.insert(std::make_pair<std::string, std::string>(
-            V.ParentPkg().Name(), outs.str()));
-      } else {
-         ListSingleVersion(CacheFile, records, V, outs, includeSummary);
-         output_map.insert(std::make_pair<std::string, std::string>(
-                           V.ParentPkg().Name(), outs.str()));
-      }
+         ListAllVersions(CacheFile, records, V.ParentPkg(), outs, format);
+      else
+         ListSingleVersion(CacheFile, records, V, outs, format);
+      output_map.insert(std::make_pair<std::string, std::string>(
+	       V.ParentPkg().Name(), outs.str()));
    }
    }
 
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
    // output the sorted map
+   std::map<std::string, std::string>::const_iterator K;
    for (K = output_map.begin(); K != output_map.end(); ++K)
    for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
       std::cout << (*K).second << std::endl;
 
 
-
    // be nice and tell the user if there is more to see
    // be nice and tell the user if there is more to see
    if (bag.size() == 1 && ShowAllVersions == false)
    if (bag.size() == 1 && ShowAllVersions == false)
    {
    {
       // start with -1 as we already displayed one version
       // start with -1 as we already displayed one version
       int versions = -1;
       int versions = -1;
       pkgCache::VerIterator Ver = *bag.begin();
       pkgCache::VerIterator Ver = *bag.begin();
-      for ( ; Ver.end() == false; Ver++)
-         versions++;
+      for ( ; Ver.end() == false; ++Ver)
+         ++versions;
       if (versions > 0)
       if (versions > 0)
          _error->Notice(P_("There is %i additional version. Please use the '-a' switch to see it", "There are %i additional versions. Please use the '-a' switch to see them.", versions), versions);
          _error->Notice(P_("There is %i additional version. Please use the '-a' switch to see it", "There are %i additional versions. Please use the '-a' switch to see them.", versions), versions);
    }
    }

+ 205 - 172
apt-private/private-output.cc

@@ -94,7 +94,7 @@ bool InitOutput()							/*{{{*/
 static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
 static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
 {
 {
    std::string suite = "";
    std::string suite = "";
-   if (ver && ver.FileList() && ver.FileList())
+   if (ver && ver.FileList())
    {
    {
       pkgCache::VerFileIterator VF = ver.FileList();
       pkgCache::VerFileIterator VF = ver.FileList();
       for (; VF.end() == false ; ++VF)
       for (; VF.end() == false ; ++VF)
@@ -118,7 +118,7 @@ static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
    std::string flags_str;
    std::string flags_str;
    if (state.NowBroken())
    if (state.NowBroken())
       flags_str = "B";
       flags_str = "B";
-   if (P.CurrentVer() && state.Upgradable())
+   if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
       flags_str = "g";
       flags_str = "g";
    else if (P.CurrentVer() != NULL)
    else if (P.CurrentVer() != NULL)
       flags_str = "i";
       flags_str = "i";
@@ -164,15 +164,26 @@ static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator
 									/*}}}*/
 									/*}}}*/
 static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
 {
-   pkgPolicy *policy = CacheFile.GetPolicy();
-   pkgCache::VerIterator inst = P.CurrentVer();
-   pkgCache::VerIterator cand = policy->GetCandidateVer(P);
-
-   // this may happen for packages in dpkg "deinstall ok config-file" state
-   if (inst.IsGood() == false && cand.IsGood() == false)
-      return P.VersionList().Arch();
-
-   return inst ? inst.Arch() : cand.Arch();
+   if (P->CurrentVer == 0)
+   {
+      pkgDepCache * const DepCache = CacheFile.GetDepCache();
+      pkgDepCache::StateCache const &state = (*DepCache)[P];
+      if (state.CandidateVer != NULL)
+      {
+	 pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer);
+	 return CandV.Arch();
+      }
+      else
+      {
+	 pkgCache::VerIterator const V = P.VersionList();
+	 if (V.end() == false)
+	    return V.Arch();
+	 else
+	    return P.Arch();
+      }
+   }
+   else
+      return P.CurrentVer().Arch();
 }
 }
 									/*}}}*/
 									/*}}}*/
 static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
@@ -196,80 +207,90 @@ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &reco
    return ShortDescription;
    return ShortDescription;
 }
 }
 									/*}}}*/
 									/*}}}*/
-void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
-                       pkgCache::VerIterator V, std::ostream &out,
-                       bool include_summary)
+static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 {
 {
-   pkgCache::PkgIterator P = V.ParentPkg();
+   pkgPolicy *policy = CacheFile.GetPolicy();
 
 
-   pkgDepCache *DepCache = CacheFile.GetDepCache();
-   pkgDepCache::StateCache &state = (*DepCache)[P];
+   pkgCache::VerIterator ver;
+   if (P->CurrentVer != 0)
+      ver = P.CurrentVer();
+   else
+      ver = policy->GetCandidateVer(P);
 
 
-   std::string suite = GetArchiveSuite(CacheFile, V);
-   std::string name_str = P.Name();
+   std::string const EmptyDescription = "(none)";
+   if(ver.end() == true)
+      return EmptyDescription;
+
+   pkgCache::DescIterator const Desc = ver.TranslatedDescription();
+   pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
+   std::string const longdesc = parser.LongDesc();
+   if (longdesc.empty() == true)
+      return EmptyDescription;
+   return SubstVar(longdesc, "\n ", "\n  ");
+}
+									/*}}}*/
+void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
+                       pkgCache::VerIterator const &V, std::ostream &out,
+                       std::string const &format)
+{
+   pkgCache::PkgIterator const P = V.ParentPkg();
+   pkgDepCache * const DepCache = CacheFile.GetDepCache();
+   pkgDepCache::StateCache const &state = (*DepCache)[P];
 
 
+   std::string output;
    if (_config->FindB("APT::Cmd::use-format", false))
    if (_config->FindB("APT::Cmd::use-format", false))
+      output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
+   else
+      output = format;
+
+   // FIXME: some of these names are really icky – and all is nowhere documented
+   output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
+   output = SubstVar(output, "${Package}", P.Name());
+   std::string const ArchStr = GetArchitecture(CacheFile, P);
+   output = SubstVar(output, "${Architecture}", ArchStr);
+   std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P);
+   output = SubstVar(output, "${installed:Version}", InstalledVerStr);
+   std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P);
+   output = SubstVar(output, "${candidate:Version}", CandidateVerStr);
+   std::string const VersionStr = GetVersion(CacheFile, V);
+   output = SubstVar(output, "${Version}", VersionStr);
+   output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
+
+   std::string StatusStr = "";
+   if (P->CurrentVer != 0)
    {
    {
-      std::string format = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
-      std::string output = format;
-   
-      output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
-      output = SubstVar(output, "${Package}", name_str);
-      output = SubstVar(output, "${installed:Version}", GetInstalledVersion(CacheFile, P));
-      output = SubstVar(output, "${candidate:Version}", GetCandidateVersion(CacheFile, P));
-      output = SubstVar(output, "${Version}", GetVersion(CacheFile, V));
-      output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
-      output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
-      out << output << std::endl;
-   } else {
-      // raring/linux-kernel version [upradable: new-version]
-      //    description
-      pkgPolicy *policy = CacheFile.GetPolicy();
-      std::string VersionStr = GetVersion(CacheFile, V);
-      std::string CandidateVerStr = GetCandidateVersion(CacheFile, P);
-      std::string InstalledVerStr = GetInstalledVersion(CacheFile, P);
-      std::string StatusStr;
-      if(P.CurrentVer() == V && state.Upgradable()) {
-         strprintf(StatusStr, _("[installed,upgradable to: %s]"),
-                   CandidateVerStr.c_str());
-      } else if (P.CurrentVer() == V) {
-         if(!V.Downloadable())
-            StatusStr = _("[installed,local]");
-         else
-            if(V.Automatic() && state.Garbage)
-               StatusStr = _("[installed,auto-removable]");
-            else if (state.Flags & pkgCache::Flag::Auto)
-               StatusStr = _("[installed,automatic]");
-            else
-               StatusStr = _("[installed]");
-      } else if (P.CurrentVer() && 
-                 policy->GetCandidateVer(P) == V && 
-                 state.Upgradable()) {
-            strprintf(StatusStr, _("[upgradable from: %s]"),
-                      InstalledVerStr.c_str());
-      } else {
-         if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
-            StatusStr = _("[residual-config]");
-         else
-            StatusStr = "";
-      }
-      out << std::setiosflags(std::ios::left)
-          << _config->Find("APT::Color::Highlight", "")
-          << name_str 
-          << _config->Find("APT::Color::Neutral", "")
-          << "/" << suite
-          << " "
-          << VersionStr << " " 
-          << GetArchitecture(CacheFile, P);
-      if (StatusStr != "") 
-         out << " " << StatusStr;
-      if (include_summary)
+      if (P.CurrentVer() == V)
       {
       {
-         out << std::endl 
-             << "  " << GetShortDescription(CacheFile, records, P)
-             << std::endl;
+	 if (state.Upgradable() && state.CandidateVer != NULL)
+	    strprintf(StatusStr, _("[installed,upgradable to: %s]"),
+		  CandidateVerStr.c_str());
+	 else if (V.Downloadable() == false)
+	    StatusStr = _("[installed,local]");
+	 else if(V.Automatic() == true && state.Garbage == true)
+	    StatusStr = _("[installed,auto-removable]");
+	 else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+	    StatusStr = _("[installed,automatic]");
+	 else
+	    StatusStr = _("[installed]");
       }
       }
+      else if (state.CandidateVer == V && state.Upgradable())
+	 strprintf(StatusStr, _("[upgradable from: %s]"),
+	       InstalledVerStr.c_str());
    }
    }
+   else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
+      StatusStr = _("[residual-config]");
+   output = SubstVar(output, "${apt:Status}", StatusStr);
+   output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", ""));
+   output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", ""));
+   output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
+   output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
+   output = SubstVar(output, "${ }${ }", "${ }");
+   output = SubstVar(output, "${ }\n", "\n");
+   output = SubstVar(output, "${ }", " ");
+   if (APT::String::Endswith(output, " ") == true)
+      output.erase(output.length() - 1);
+
+   out << output;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ShowList - Show a list						/*{{{*/
 // ShowList - Show a list						/*{{{*/
@@ -344,129 +365,141 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList)
            Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
            Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
            Depends: libsasl7 but it is not going to be installed   
            Depends: libsasl7 but it is not going to be installed   
  */
  */
-void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
+static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
 {
 {
-   if (Cache->BrokenCount() == 0)
+   if (Now == true)
+   {
+      if ((*Cache)[Pkg].NowBroken() == false)
+	 return;
+   }
+   else
+   {
+      if ((*Cache)[Pkg].InstBroken() == false)
+	 return;
+   }
+
+   // Print out each package and the failed dependencies
+   out << " " << Pkg.FullName(true) << " :";
+   unsigned const Indent = Pkg.FullName(true).size() + 3;
+   bool First = true;
+   pkgCache::VerIterator Ver;
+
+   if (Now == true)
+      Ver = Pkg.CurrentVer();
+   else
+      Ver = (*Cache)[Pkg].InstVerIter(*Cache);
+
+   if (Ver.end() == true)
+   {
+      out << endl;
       return;
       return;
+   }
 
 
-   out << _("The following packages have unmet dependencies:") << endl;
-   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
    {
    {
-      pkgCache::PkgIterator I(Cache,Cache.List[J]);
-      
+      // Compute a single dependency element (glob or)
+      pkgCache::DepIterator Start;
+      pkgCache::DepIterator End;
+      D.GlobOr(Start,End); // advances D
+
+      if ((*Cache)->IsImportantDep(End) == false)
+	 continue;
+
       if (Now == true)
       if (Now == true)
       {
       {
-	 if (Cache[I].NowBroken() == false)
+	 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
 	    continue;
 	    continue;
       }
       }
       else
       else
       {
       {
-	 if (Cache[I].InstBroken() == false)
+	 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
 	    continue;
 	    continue;
       }
       }
-      
-      // Print out each package and the failed dependencies
-      out << " " << I.FullName(true) << " :";
-      unsigned const Indent = I.FullName(true).size() + 3;
-      bool First = true;
-      pkgCache::VerIterator Ver;
-      
-      if (Now == true)
-	 Ver = I.CurrentVer();
-      else
-	 Ver = Cache[I].InstVerIter(Cache);
-      
-      if (Ver.end() == true)
-      {
-	 out << endl;
-	 continue;
-      }
-      
-      for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
+
+      bool FirstOr = true;
+      while (1)
       {
       {
-	 // Compute a single dependency element (glob or)
-	 pkgCache::DepIterator Start;
-	 pkgCache::DepIterator End;
-	 D.GlobOr(Start,End); // advances D
+	 if (First == false)
+	    for (unsigned J = 0; J != Indent; J++)
+	       out << ' ';
+	 First = false;
 
 
-	 if (Cache->IsImportantDep(End) == false)
-	    continue;
-	 
-	 if (Now == true)
+	 if (FirstOr == false)
 	 {
 	 {
-	    if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
-	       continue;
+	    for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
+	       out << ' ';
 	 }
 	 }
 	 else
 	 else
+	    out << ' ' << End.DepType() << ": ";
+	 FirstOr = false;
+
+	 out << Start.TargetPkg().FullName(true);
+
+	 // Show a quick summary of the version requirements
+	 if (Start.TargetVer() != 0)
+	    out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
+
+	 /* Show a summary of the target package if possible. In the case
+	    of virtual packages we show nothing */
+	 pkgCache::PkgIterator Targ = Start.TargetPkg();
+	 if (Targ->ProvidesList == 0)
 	 {
 	 {
-	    if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
-	       continue;
-	 }
-	 
-	 bool FirstOr = true;
-	 while (1)
-	 {
-	    if (First == false)
-	       for (unsigned J = 0; J != Indent; J++)
-		  out << ' ';
-	    First = false;
+	    out << ' ';
+	    pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
+	    if (Now == true)
+	       Ver = Targ.CurrentVer();
 
 
-	    if (FirstOr == false)
+	    if (Ver.end() == false)
 	    {
 	    {
-	       for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
-		  out << ' ';
+	       if (Now == true)
+		  ioprintf(out,_("but %s is installed"),Ver.VerStr());
+	       else
+		  ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
 	    }
 	    }
 	    else
 	    else
-	       out << ' ' << End.DepType() << ": ";
-	    FirstOr = false;
-	    
-	    out << Start.TargetPkg().FullName(true);
-	 
-	    // Show a quick summary of the version requirements
-	    if (Start.TargetVer() != 0)
-	       out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
-	    
-	    /* Show a summary of the target package if possible. In the case
-	       of virtual packages we show nothing */	 
-	    pkgCache::PkgIterator Targ = Start.TargetPkg();
-	    if (Targ->ProvidesList == 0)
 	    {
 	    {
-	       out << ' ';
-	       pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
-	       if (Now == true)
-		  Ver = Targ.CurrentVer();
-	       	    
-	       if (Ver.end() == false)
+	       if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
 	       {
 	       {
-		  if (Now == true)
-		     ioprintf(out,_("but %s is installed"),Ver.VerStr());
+		  if (Targ->ProvidesList == 0)
+		     out << _("but it is not installable");
 		  else
 		  else
-		     ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
-	       }	       
+		     out << _("but it is a virtual package");
+	       }
 	       else
 	       else
-	       {
-		  if (Cache[Targ].CandidateVerIter(Cache).end() == true)
-		  {
-		     if (Targ->ProvidesList == 0)
-			out << _("but it is not installable");
-		     else
-			out << _("but it is a virtual package");
-		  }		  
-		  else
-		     out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
-	       }	       
+		  out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
 	    }
 	    }
-	    
-	    if (Start != End)
-	       out << _(" or");
-	    out << endl;
-	    
-	    if (Start == End)
-	       break;
-	    ++Start;
-	 }	 
-      }	    
-   }   
+	 }
+
+	 if (Start != End)
+	    out << _(" or");
+	 out << endl;
+
+	 if (Start == End)
+	    break;
+	 ++Start;
+      }
+   }
+}
+void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
+{
+   if (Cache->BrokenCount() == 0)
+      return;
+
+   out << _("The following packages have unmet dependencies:") << endl;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator const I(Cache,Cache.List[J]);
+      ShowBrokenPackage(out, &Cache, I, Now);
+   }
+}
+void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
+{
+   if (Cache->BrokenCount() == 0)
+      return;
+
+   out << _("The following packages have unmet dependencies:") << endl;
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
+      ShowBrokenPackage(out, &Cache, Pkg, Now);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ShowNew - Show packages to newly install				/*{{{*/
 // ShowNew - Show packages to newly install				/*{{{*/

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

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

+ 58 - 24
apt-private/private-search.cc

@@ -32,61 +32,95 @@ bool FullTextSearch(CommandLine &CmdL)					/*{{{*/
    pkgCacheFile CacheFile;
    pkgCacheFile CacheFile;
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
    pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
-   pkgRecords records(CacheFile);
    if (unlikely(Cache == NULL || Plcy == NULL))
    if (unlikely(Cache == NULL || Plcy == NULL))
       return false;
       return false;
 
 
-   const char **patterns;
-   patterns = CmdL.FileList + 1;
+   // Make sure there is at least one argument
+   unsigned int const NumPatterns = CmdL.FileSize() -1;
+   if (NumPatterns < 1)
+      return _error->Error(_("You must give at least one search pattern"));
+
+#define APT_FREE_PATTERNS() for (std::vector<regex_t>::iterator P = Patterns.begin(); \
+      P != Patterns.end(); ++P) { regfree(&(*P)); }
+
+   // Compile the regex pattern
+   std::vector<regex_t> Patterns;
+   for (unsigned int I = 0; I != NumPatterns; ++I)
+   {
+      regex_t pattern;
+      if (regcomp(&pattern, CmdL.FileList[I + 1], REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+      {
+	 APT_FREE_PATTERNS();
+	 return _error->Error("Regex compilation error");
+      }
+      Patterns.push_back(pattern);
+   }
+
+   bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly", false);
 
 
    std::map<std::string, std::string> output_map;
    std::map<std::string, std::string> output_map;
-   std::map<std::string, std::string>::const_iterator K;
 
 
    LocalitySortedVersionSet bag;
    LocalitySortedVersionSet bag;
    OpTextProgress progress(*_config);
    OpTextProgress progress(*_config);
    progress.OverallProgress(0, 100, 50,  _("Sorting"));
    progress.OverallProgress(0, 100, 50,  _("Sorting"));
-   GetLocalitySortedVersionSet(CacheFile, bag, progress);
+   GetLocalitySortedVersionSet(CacheFile, &bag, &progress);
    LocalitySortedVersionSet::iterator V = bag.begin();
    LocalitySortedVersionSet::iterator V = bag.begin();
 
 
    progress.OverallProgress(50, 100, 50,  _("Full Text Search"));
    progress.OverallProgress(50, 100, 50,  _("Full Text Search"));
    progress.SubProgress(bag.size());
    progress.SubProgress(bag.size());
+   pkgRecords records(CacheFile);
+
+   std::string format = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture}${ }${apt:Status}\n";
+   if (_config->FindB("APT::Cache::ShowFull",false) == false)
+      format += "  ${Description}\n";
+   else
+      format += "  ${LongDescription}\n";
+
    int Done = 0;
    int Done = 0;
+   std::vector<bool> PkgsDone(Cache->Head().PackageCount, false);
    for ( ;V != bag.end(); ++V)
    for ( ;V != bag.end(); ++V)
    {
    {
       if (Done%500 == 0)
       if (Done%500 == 0)
          progress.Progress(Done);
          progress.Progress(Done);
       ++Done;
       ++Done;
-      
-      int i;
+
+      // we want to list each package only once
+      pkgCache::PkgIterator const P = V.ParentPkg();
+      if (PkgsDone[P->ID] == true)
+	 continue;
+
+      char const * const PkgName = P.Name();
       pkgCache::DescIterator Desc = V.TranslatedDescription();
       pkgCache::DescIterator Desc = V.TranslatedDescription();
       pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
       pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
-     
+      std::string const LongDesc = parser.LongDesc();
+
       bool all_found = true;
       bool all_found = true;
-      for(i=0; patterns[i] != NULL; ++i)
+      for (std::vector<regex_t>::const_iterator pattern = Patterns.begin();
+	    pattern != Patterns.end(); ++pattern)
       {
       {
-         // FIXME: use regexp instead of simple find()
-         const char *pattern = patterns[i];
-         all_found &=  (
-            strstr(V.ParentPkg().Name(), pattern) != NULL ||
-            strcasestr(parser.ShortDesc().c_str(), pattern) != NULL ||
-            strcasestr(parser.LongDesc().c_str(), pattern) != NULL);
-         // search patterns are AND by default so we can skip looking further
-         // on the first mismatch
-         if(all_found == false)
-            break;
+	 if (regexec(&(*pattern), PkgName, 0, 0, 0) == 0)
+	    continue;
+	 else if (NamesOnly == false && regexec(&(*pattern), LongDesc.c_str(), 0, 0, 0) == 0)
+	    continue;
+	 // search patterns are AND, so one failing fails all
+	 all_found = false;
+	 break;
       }
       }
-      if (all_found)
+      if (all_found == true)
       {
       {
-            std::stringstream outs;
-            ListSingleVersion(CacheFile, records, V, outs);
-            output_map.insert(std::make_pair<std::string, std::string>(
-                                 V.ParentPkg().Name(), outs.str()));
+	 PkgsDone[P->ID] = true;
+	 std::stringstream outs;
+	 ListSingleVersion(CacheFile, records, V, outs, format);
+	 output_map.insert(std::make_pair<std::string, std::string>(
+		  PkgName, outs.str()));
       }
       }
    }
    }
+   APT_FREE_PATTERNS();
    progress.Done();
    progress.Done();
 
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
    // output the sorted map
+   std::map<std::string, std::string>::const_iterator K;
    for (K = output_map.begin(); K != output_map.end(); ++K)
    for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
       std::cout << (*K).second << std::endl;
 
 

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

@@ -141,16 +141,16 @@ bool ShowPackage(CommandLine &CmdL)					/*{{{*/
 {
 {
    pkgCacheFile CacheFile;
    pkgCacheFile CacheFile;
    CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
    CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
-   APT::VersionList::Version const select = _config->FindB("APT::Cache::AllVersions", false) ?
-			APT::VersionList::ALL : APT::VersionList::CANDIDATE;
+   APT::CacheSetHelper::VerSelector const select = _config->FindB("APT::Cache::AllVersions", false) ?
+			APT::CacheSetHelper::ALL : APT::CacheSetHelper::CANDIDATE;
    APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
    APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
    for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
    for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
       if (DisplayRecord(CacheFile, Ver, c1out) == false)
       if (DisplayRecord(CacheFile, Ver, c1out) == false)
 	 return false;
 	 return false;
 
 
-   if (select == APT::VersionList::CANDIDATE)
+   if (select == APT::CacheSetHelper::CANDIDATE)
    {
    {
-      APT::VersionList const verset_all = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::VersionList::ALL, helper);
+      APT::VersionList const verset_all = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::CacheSetHelper::ALL, helper);
       int const records = verset_all.size() - verset.size();
       int const records = verset_all.size() - verset.size();
       if (records > 0)
       if (records > 0)
          _error->Notice(P_("There is %i additional record. Please use the '-a' switch to see it", "There are %i additional records. Please use the '-a' switch to see them.", records), records);
          _error->Notice(P_("There is %i additional record. Please use the '-a' switch to see it", "There are %i additional records. Please use the '-a' switch to see them.", records), records);

+ 29 - 1
apt-private/private-update.cc

@@ -56,10 +56,17 @@ bool DoUpdate(CommandLine &CmdL)
       if (List->GetIndexes(&Fetcher,true) == false)
       if (List->GetIndexes(&Fetcher,true) == false)
 	 return false;
 	 return false;
 
 
+      std::string compExt = APT::Configuration::getCompressionTypes()[0];
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); ++I)
       for (; I != Fetcher.UriEnd(); ++I)
-	 c1out << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
+      {
+         std::string FileName = flNotDir(I->Owner->DestFile);
+         if(compExt.empty() == false && 
+            APT::String::Endswith(FileName, compExt))
+            FileName = FileName.substr(0, FileName.size() - compExt.size() - 1);
+	 c1out << '\'' << I->URI << "' " << FileName << ' ' << 
             I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
             I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
+      }
       return true;
       return true;
    }
    }
 
 
@@ -75,6 +82,27 @@ bool DoUpdate(CommandLine &CmdL)
 	 return false;
 	 return false;
    }
    }
 
 
+   // show basic stats (if the user whishes)
+   if (_config->FindB("APT::Cmd::Show-Update-Stats", false) == true)
+   {
+      int upgradable = 0;
+      Cache.Open();
+      for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() != true; ++I)
+      {
+         pkgDepCache::StateCache &state = Cache[I];
+         if (I->CurrentVer != 0 && state.Upgradable() && state.CandidateVer != NULL)
+            upgradable++;
+      }
+      const char *msg = P_(
+         "%i package can be upgraded. Run 'apt list --upgradable' to see it.\n",
+         "%i packages can be upgraded. Run 'apt list --upgradable' to see them.\n",
+         upgradable);
+      if (upgradable == 0)
+         c1out << _("All packages are up to date.") << std::endl;
+      else
+         ioprintf(c1out, msg, upgradable);
+   }
+
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 3 - 13
apt-private/private-upgrade.cc

@@ -22,19 +22,9 @@ static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
       return false;
       return false;
 
 
-   c0out << _("Calculating upgrade... ") << std::flush;
-   if (APT::Upgrade::Upgrade(Cache, UpgradeFlags) == false)
-   {
-      c0out << _("Failed") << std::endl;
-      ShowBroken(c1out,Cache,false);
-      return _error->Error(_("Internal error, Upgrade broke stuff"));
-   }
-   c0out << _("Done") << std::endl;
-
-   // parse additional cmdline pkg manipulation switches
-   if(!DoCacheManipulationFromCommandLine(CmdL, Cache))
+   if(!DoCacheManipulationFromCommandLine(CmdL, Cache, UpgradeFlags))
       return false;
       return false;
-   
+
    return InstallPackages(Cache,true);
    return InstallPackages(Cache,true);
 }
 }
 
 
@@ -43,7 +33,7 @@ static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
 /* Intelligent upgrader that will install and remove packages at will */
 /* Intelligent upgrader that will install and remove packages at will */
 bool DoDistUpgrade(CommandLine &CmdL)
 bool DoDistUpgrade(CommandLine &CmdL)
 {
 {
-   return UpgradeHelper(CmdL, 0);
+   return UpgradeHelper(CmdL, APT::Upgrade::ALLOW_EVERYTHING);
 }
 }
 									/*}}}*/
 									/*}}}*/
 bool DoUpgrade(CommandLine &CmdL)					/*{{{*/
 bool DoUpgrade(CommandLine &CmdL)					/*{{{*/

+ 41 - 17
apt-private/private-utils.cc

@@ -8,45 +8,69 @@
 #include <cstdlib>
 #include <cstdlib>
 #include <unistd.h>
 #include <unistd.h>
 
 
-// DisplayFileInPager - Display File with pager        			/*{{{*/
-void DisplayFileInPager(std::string filename)
+// DisplayFileInPager - Display File with pager				/*{{{*/
+void DisplayFileInPager(std::string const &filename)
 {
 {
-   std::string pager = _config->Find("Dir::Bin::Pager", 
-                                        "/usr/bin/sensible-pager");
-
    pid_t Process = ExecFork();
    pid_t Process = ExecFork();
    if (Process == 0)
    if (Process == 0)
    {
    {
       const char *Args[3];
       const char *Args[3];
-      Args[0] = pager.c_str();
       Args[1] = filename.c_str();
       Args[1] = filename.c_str();
-      Args[2] = 0;
+      Args[2] = NULL;
+      if (isatty(STDOUT_FILENO) == 1)
+      {
+	 // likely installed, provided by sensible-utils
+	 std::string const pager = _config->Find("Dir::Bin::Pager",
+	       "sensible-pager");
+	 Args[0] = pager.c_str();
+	 execvp(Args[0],(char **)Args);
+	 // lets try some obvious alternatives
+	 Args[0] = getenv("PAGER");
+	 if (Args[0] != NULL)
+	    execvp(Args[0],(char **)Args);
+
+	 Args[0] = "pager";
+	 execvp(Args[0],(char **)Args);
+      }
+      // we could read the file ourselves, but… meh
+      Args[0] = "cat";
       execvp(Args[0],(char **)Args);
       execvp(Args[0],(char **)Args);
       exit(100);
       exit(100);
    }
    }
-         
+
    // Wait for the subprocess
    // Wait for the subprocess
-   ExecWait(Process, "sensible-pager", false);
+   ExecWait(Process, "pager", false);
 }
 }
 									/*}}}*/
 									/*}}}*/
-// EditFileInSensibleEditor - Edit File with editor    			/*{{{*/
-void EditFileInSensibleEditor(std::string filename)
+// EditFileInSensibleEditor - Edit File with editor			/*{{{*/
+void EditFileInSensibleEditor(std::string const &filename)
 {
 {
-   std::string editor = _config->Find("Dir::Bin::Editor", 
-                                        "/usr/bin/sensible-editor");
-
    pid_t Process = ExecFork();
    pid_t Process = ExecFork();
    if (Process == 0)
    if (Process == 0)
    {
    {
+      // likely installed, provided by sensible-utils
+      std::string const editor = _config->Find("Dir::Bin::Editor",
+	    "sensible-editor");
       const char *Args[3];
       const char *Args[3];
       Args[0] = editor.c_str();
       Args[0] = editor.c_str();
       Args[1] = filename.c_str();
       Args[1] = filename.c_str();
-      Args[2] = 0;
+      Args[2] = NULL;
+      execvp(Args[0],(char **)Args);
+      // the usual suspects we can try as an alternative
+      Args[0] = getenv("VISUAL");
+      if (Args[0] != NULL)
+	 execvp(Args[0],(char **)Args);
+
+      Args[0] = getenv("EDITOR");
+      if (Args[0] != NULL)
+	 execvp(Args[0],(char **)Args);
+
+      Args[0] = "editor";
       execvp(Args[0],(char **)Args);
       execvp(Args[0],(char **)Args);
       exit(100);
       exit(100);
    }
    }
-         
+
    // Wait for the subprocess
    // Wait for the subprocess
-   ExecWait(Process, "sensible-editor", false);
+   ExecWait(Process, "editor", false);
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 2 - 2
apt-private/private-utils.h

@@ -5,7 +5,7 @@
 
 
 #include <string>
 #include <string>
 
 
-APT_PUBLIC void DisplayFileInPager(std::string filename);
-APT_PUBLIC void EditFileInSensibleEditor(std::string filename);
+APT_PUBLIC void DisplayFileInPager(std::string const &filename);
+APT_PUBLIC void EditFileInSensibleEditor(std::string const &filename);
 
 
 #endif
 #endif

+ 4 - 0
buildlib/config.h.in

@@ -28,6 +28,10 @@
 /* If there is no socklen_t, define this for the netdb shim */
 /* If there is no socklen_t, define this for the netdb shim */
 #undef NEED_SOCKLEN_T_DEFINE
 #undef NEED_SOCKLEN_T_DEFINE
 
 
+/* We need the getresuid() function */
+#undef HAVE_GETRESUID
+#undef HAVE_GETRESGID
+
 /* Define to the size of the filesize containing structures */
 /* Define to the size of the filesize containing structures */
 #undef _FILE_OFFSET_BITS
 #undef _FILE_OFFSET_BITS
 
 

+ 0 - 60
buildlib/debiandoc.mak

@@ -1,60 +0,0 @@
-# -*- make -*-
-
-# This processes debian-doc sgml to produce html and plain text output
-
-# Input
-# $(SOURCE) - The documents to use
-
-# All output is writtin to files in the build doc directory
-
-# See defaults.mak for information about LOCAL
-
-# Some local definitions
-LOCAL := debiandoc-$(firstword $(SOURCE))
-$(LOCAL)-HTML := $(addsuffix .html,$(addprefix $(DOC)/,$(basename $(SOURCE))))
-$(LOCAL)-TEXT := $(addsuffix .text,$(addprefix $(DOC)/,$(basename $(SOURCE))))
-
-debiandoc:
-
-#---------
-
-# Rules to build HTML documentations
-ifdef DEBIANDOC_HTML
-
-# Install generation hooks
-debiandoc: $($(LOCAL)-HTML)
-veryclean: veryclean/html/$(LOCAL)
-
-vpath %.sgml $(SUBDIRS)
-$(DOC)/%.html: %.sgml
-	echo Creating html for $< to $@
-	-rm -rf $@
-	(HERE=`pwd`; cd $(@D) && $(DEBIANDOC_HTML) $(DEBIANDOC_HTML_OPTIONS) $$HERE/$<) || exit 199
-
-# Clean rule
-.PHONY: veryclean/html/$(LOCAL)
-veryclean/html/$(LOCAL):
-	-rm -rf $($(@F)-HTML)
-	
-endif
-
-#---------
-
-# Rules to build Text documentations
-ifdef DEBIANDOC_TEXT
-
-# Install generation hooks
-debiandoc: $($(LOCAL)-TEXT)
-veryclean: veryclean/text/$(LOCAL)
-
-vpath %.sgml $(SUBDIRS)
-$(DOC)/%.text: %.sgml
-	echo Creating text for $< to $@
-	$(DEBIANDOC_TEXT) -O $< > $@ || exit 198
-
-# Clean rule
-.PHONY: veryclean/text/$(LOCAL)
-veryclean/text/$(LOCAL):
-	-rm -rf $($(@F)-TEXT)
-	
-endif

+ 0 - 0
buildlib/defaults.mak


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor