From 6c139d6e362f04a1582e8a8f511f8aeab031fecf Mon Sep 17 00:00:00 2001
From: Arch Librarian <arch@canonical.com>
Date: Mon, 20 Sep 2004 16:50:41 +0000
Subject: [PATCH] Sync Author: jgg Date: 1998-07-07 04:17:00 GMT Sync

---
 apt-pkg/algorithms.cc            | 732 +++++++++++++++++++++++++
 apt-pkg/algorithms.h             |  91 ++++
 apt-pkg/cacheiterators.h         |  21 +-
 apt-pkg/contrib/configuration.cc | 137 +++++
 apt-pkg/contrib/configuration.h  |  61 +++
 apt-pkg/contrib/error.cc         |  74 ++-
 apt-pkg/contrib/error.h          |  15 +-
 apt-pkg/contrib/fileutl.cc       |   5 +-
 apt-pkg/contrib/fileutl.h        |   6 +-
 apt-pkg/contrib/mmap.cc          |   6 +-
 apt-pkg/contrib/mmap.h           |   6 +-
 apt-pkg/contrib/strutl.cc        | 343 ++++++++++++
 apt-pkg/contrib/strutl.h         |  36 ++
 apt-pkg/deb/deblistparser.cc     |  90 +--
 apt-pkg/depcache.cc              | 903 +++++++++++++++++++++++++++++++
 apt-pkg/depcache.h               | 189 +++++++
 apt-pkg/orderlist.cc             | 829 ++++++++++++++++++++++++++++
 apt-pkg/orderlist.h              | 123 +++++
 apt-pkg/packagemanager.cc        | 548 +++++++++++++++++++
 apt-pkg/packagemanager.h         |  84 +++
 apt-pkg/pkgcache.cc              |  24 +-
 apt-pkg/pkgcache.h               |  42 +-
 apt-pkg/pkgcachegen.cc           |   6 +-
 apt-pkg/pkgcachegen.h            |   6 +-
 apt-pkg/sourcelist.cc            | 465 ++++++++++++++++
 apt-pkg/sourcelist.h             |  78 +++
 apt-pkg/tagfile.cc               |   6 +-
 apt-pkg/tagfile.h                |   6 +-
 apt-pkg/version.cc               |  18 +-
 apt-pkg/version.h                |   6 +-
 30 files changed, 4841 insertions(+), 115 deletions(-)
 create mode 100644 apt-pkg/algorithms.cc
 create mode 100644 apt-pkg/algorithms.h
 create mode 100644 apt-pkg/contrib/configuration.cc
 create mode 100644 apt-pkg/contrib/configuration.h
 create mode 100644 apt-pkg/contrib/strutl.cc
 create mode 100644 apt-pkg/contrib/strutl.h
 create mode 100644 apt-pkg/depcache.cc
 create mode 100644 apt-pkg/depcache.h
 create mode 100644 apt-pkg/orderlist.cc
 create mode 100644 apt-pkg/orderlist.h
 create mode 100644 apt-pkg/packagemanager.cc
 create mode 100644 apt-pkg/packagemanager.h
 create mode 100644 apt-pkg/sourcelist.cc
 create mode 100644 apt-pkg/sourcelist.h

diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
new file mode 100644
index 000000000..e3012489d
--- /dev/null
+++ b/apt-pkg/algorithms.cc
@@ -0,0 +1,732 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: algorithms.cc,v 1.1 1998/07/07 04:17:00 jgg Exp $
+/* ######################################################################
+
+   Algorithms - A set of misc algorithms
+
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/algorithms.h"
+#endif 
+#include <pkglib/algorithms.h>
+#include <pkglib/error.h>
+#include <pkglib/pkgelement.h>
+#include <iostream.h>
+									/*}}}*/
+
+pkgProblemResolver *pkgProblemResolver::This = 0;
+
+// Simulate::Simulate - Constructor					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgSimulate::pkgSimulate(pkgDepCache &Cache) : pkgPackageManager(Cache), 
+                            Sim(true,true)
+{
+   Flags = new unsigned char[Cache.HeaderP->PackageCount];
+   memset(Flags,0,sizeof(*Flags)*Cache.HeaderP->PackageCount);
+}
+									/*}}}*/
+// Simulate::Install - Simulate unpacking of a package			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
+{
+   // Adapt the iterator
+   PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
+   Flags[Pkg->ID] = 1;
+   
+   cout << "Inst " << Pkg.Name();
+   Sim.MarkInstall(Pkg,false);
+   
+   // Look for broken conflicts+predepends.
+   for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
+   {
+      if (Sim[I].InstallVer == 0)
+	 continue;
+      
+      for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false; D++)
+	 if (D->Type == pkgDEP_Conflicts || D->Type == pkgDEP_PreDepends)
+         {
+	    if ((Sim[D] & pkgDepCache::DepInstall) == 0)
+	    {
+	       cout << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
+	       if (D->Type == pkgDEP_Conflicts)
+		  _error->Error("Fatal, conflicts violated %s",I.Name());
+	    }	    
+	 }      
+   }
+
+   if (Sim.BrokenCount() != 0)
+      ShortBreaks();
+   else
+      cout << endl;
+   return true;
+}
+									/*}}}*/
+// Simulate::Configure - Simulate configuration of a Package		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is not an acurate simulation of relatity, we should really not
+   install the package.. For some investigations it may be necessary 
+   however. */
+bool pkgSimulate::Configure(PkgIterator iPkg)
+{
+   // Adapt the iterator
+   PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
+   
+   Flags[Pkg->ID] = 2;
+//   Sim.MarkInstall(Pkg,false);
+   if (Sim[Pkg].InstBroken() == true)
+   {
+      cout << "Conf " << Pkg.Name() << " broken" << endl;
+
+      Sim.Update();
+      
+      // Print out each package and the failed dependencies
+      for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
+      {
+	 if (Sim.IsImportantDep(D) == false || 
+	     (Sim[D] & pkgDepCache::DepInstall) != 0)
+	    continue;
+	 
+	 if (D->Type == pkgDEP_Conflicts)
+	    cout << " Conflicts:" << D.TargetPkg().Name();
+	 else
+	    cout << " Depends:" << D.TargetPkg().Name();
+      }	    
+      cout << endl;
+
+      _error->Error("Conf Broken %s",Pkg.Name());
+   }   
+   else
+      cout << "Conf " <<  Pkg.Name();
+
+   if (Sim.BrokenCount() != 0)
+      ShortBreaks();
+   else
+      cout << endl;
+   
+   return true;
+}
+									/*}}}*/
+// Simulate::Remove - Simulate the removal of a package			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSimulate::Remove(PkgIterator iPkg)
+{
+   // Adapt the iterator
+   PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
+
+   Flags[Pkg->ID] = 3;
+   Sim.MarkDelete(Pkg);
+   cout << "Remv " << Pkg.Name();
+
+   if (Sim.BrokenCount() != 0)
+      ShortBreaks();
+   else
+      cout << endl;
+
+   return true;
+}
+									/*}}}*/
+// Simulate::ShortBreaks - Print out a short line describing all breaks	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgSimulate::ShortBreaks()
+{
+   cout << " [";
+   for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
+   {
+      if (Sim[I].InstBroken() == true)
+      {
+	 if (Flags[I->ID] == 0)
+	    cout << I.Name() << ' ';
+/*	 else
+	    cout << I.Name() << "! ";*/
+      }      
+   }
+   cout << ']' << endl;
+}
+									/*}}}*/
+// ApplyStatus - Adjust for non-ok packages				/*{{{*/
+// ---------------------------------------------------------------------
+/* We attempt to change the state of the all packages that have failed
+   installation toward their real state. The ordering code will perform 
+   the necessary calculations to deal with the problems. */
+bool pkgApplyStatus(pkgDepCache &Cache)
+{
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      switch (I->CurrentState)
+      {
+	 // This means installation failed somehow
+	 case pkgSTATE_UnPacked:
+	 case pkgSTATE_HalfConfigured:
+	 Cache.MarkKeep(I);
+	 break;
+
+	 // This means removal failed
+	 case pkgSTATE_HalfInstalled:
+	 Cache.MarkDelete(I);
+	 break;
+	 
+	 default:
+	 if (I->InstState != pkgSTATE_Ok)
+	    return _error->Error("The package %s is not ok and I "
+				 "don't know how to fix it!",I.Name());
+      }
+   }
+   return true;
+}
+									/*}}}*/
+// FixBroken - Fix broken packages					/*{{{*/
+// ---------------------------------------------------------------------
+/* This autoinstalls every broken package and then runs ScoredFix on the 
+   result. */
+bool pkgFixBroken(pkgDepCache &Cache)
+{
+   // Auto upgrade all broken packages
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      if (Cache[I].NowBroken() == true)
+	 Cache.MarkInstall(I,true);
+
+   /* Fix packages that are in a NeedArchive state but don't have a
+      downloadable install version */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
+	  Cache[I].Delete() == true)
+	 continue;
+      
+      if ((Cache[I].InstVerIter(Cache).File()->Flags & pkgFLAG_NotSource) == 0)
+	 continue;
+
+      Cache.MarkInstall(I,true);
+   }
+   
+   pkgProblemResolver Fix(Cache);
+   return Fix.Resolve(true);
+}
+									/*}}}*/
+// DistUpgrade - Distribution upgrade					/*{{{*/
+// ---------------------------------------------------------------------
+/* This autoinstalls every package and then force installs every 
+   pre-existing package. This creates the initial set of conditions which 
+   most likely contain problems because too many things were installed.
+   
+   ScoredFix is used to resolve the problems.
+ */
+bool pkgDistUpgrade(pkgDepCache &Cache)
+{
+   /* Auto upgrade all installed packages, this provides the basis 
+      for the installation */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      if (I->CurrentVer != 0)
+	 Cache.MarkInstall(I,true);
+
+   /* Now, auto upgrade all essential packages - this ensures that
+      the essential packages are present and working */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      if ((I->Flags & pkgFLAG_Essential) == pkgFLAG_Essential)
+	 Cache.MarkInstall(I,true);
+   
+   /* We do it again over all previously installed packages to force 
+      conflict resolution on them all. */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      if (I->CurrentVer != 0)
+	 Cache.MarkInstall(I,false);
+
+   pkgProblemResolver Fix(Cache);
+   
+   // Hold back held packages.
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      if (I->SelectedState == pkgSTATE_Hold)
+      {
+	 Fix.Protect(I);
+	 Cache.MarkKeep(I);
+      }
+   }
+   
+   return Fix.Resolve();
+}
+									/*}}}*/
+
+// ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgProblemResolver::pkgProblemResolver(pkgDepCache &Cache) : Cache(Cache)
+{
+   // Allocate memory
+   unsigned long Size = Cache.HeaderP->PackageCount;
+   Scores = new signed short[Size];
+   Flags = new unsigned char[Size];
+   memset(Flags,0,sizeof(*Flags)*Size);
+   
+   // Set debug to true to see its decision logic
+   Debug = false;
+}
+									/*}}}*/
+// ProblemResolver::ScoreSort - Sort the list by score			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int pkgProblemResolver::ScoreSort(const void *a,const void *b)
+{
+   Package const **A = (Package const **)a;
+   Package const **B = (Package const **)b;
+   if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
+      return -1;
+   if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
+      return 1;
+   return 0;
+}
+									/*}}}*/
+// ProblemResolver::MakeScores - Make the score table			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgProblemResolver::MakeScores()
+{
+   unsigned long Size = Cache.HeaderP->PackageCount;
+   memset(Scores,0,sizeof(*Scores)*Size);
+
+   // Generate the base scores for a package based on its properties
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      if (Cache[I].InstallVer == 0)
+	 continue;
+      
+      signed short &Score = Scores[I->ID];
+      
+      /* This is arbitary, it should be high enough to elevate an
+         essantial package above most other packages but low enough
+	 to allow an obsolete essential packages to be removed by
+	 a conflicts on a powerfull normal package (ie libc6) */
+      if ((I->Flags & pkgFLAG_Essential) == pkgFLAG_Essential)
+	 Score += 100;
+
+      // We transform the priority
+      // Important Required Standard Optional Extra
+      signed short PrioMap[] = {0,3,2,1,-1,-2};
+      if (Cache[I].InstVerIter(Cache)->Priority <= 5)
+	 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
+      
+      /* This helps to fix oddball problems with conflicting packages
+         on the same level. We enhance the score of installed packages */
+      if (I->CurrentVer != 0)
+	 Score += 1;
+   }
+
+   // Now that we have the base scores we go and propogate dependencies
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      if (Cache[I].InstallVer == 0)
+	 continue;
+      
+      for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
+      {
+	 if (D->Type == pkgDEP_Depends || D->Type == pkgDEP_PreDepends)
+	    Scores[D.TargetPkg()->ID]++;
+      }
+   }   
+   
+   // Copy the scores to advoid additive looping
+   signed short *OldScores = new signed short[Size];
+   memcpy(OldScores,Scores,sizeof(*Scores)*Size);
+      
+   /* Now we cause 1 level of dependency inheritance, that is we add the 
+      score of the packages that depend on the target Package. This 
+      fortifies high scoring packages */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      if (Cache[I].InstallVer == 0)
+	 continue;
+      
+      for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
+      {
+	 // Only do it for the install version
+	 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
+	     (D->Type != pkgDEP_Depends && D->Type != pkgDEP_PreDepends))
+	    continue;	 
+	 
+	 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
+      }      
+   }
+
+   /* Now we propogate along provides. This makes the packages that 
+      provide important packages extremely important */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
+      {
+	 // Only do it once per package
+	 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
+	    continue;
+	 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
+      }
+   }
+
+   /* Protected things are pushed really high up. This number should put them
+      ahead of everything */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      if ((Flags[I->ID] & Protected) != 0)
+	 Scores[I->ID] += 10000;
+   
+   delete [] OldScores;
+}
+									/*}}}*/
+// ProblemResolver::DoUpgrade - Attempt to upgrade this package		/*{{{*/
+// ---------------------------------------------------------------------
+/* This goes through and tries to reinstall packages to make this package
+   installable */
+bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
+{
+   if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
+      return false;
+   Flags[Pkg->ID] &= ~Upgradable;
+   
+   bool WasKept = Cache[Pkg].Keep();
+   Cache.MarkInstall(Pkg,false);
+
+   // Isolate the problem dependency
+   bool Fail = false;
+   for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
+   {
+      // Compute a single dependency element (glob or)
+      pkgCache::DepIterator Start = D;
+      pkgCache::DepIterator End = D;
+      unsigned char State = 0;
+      for (bool LastOR = true; D.end() == false && LastOR == true; D++)
+      {
+	 State |= Cache[D];
+	 LastOR = (D->CompareOp & pkgOP_OR) == pkgOP_OR;
+	 if (LastOR == true)
+	    End = D;
+      }
+      
+      // We only worry about critical deps.
+      if (End.IsCritical() != true)
+	 continue;
+      
+      // Dep is ok
+      if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
+	 continue;
+      
+      // Hm, the group is broken.. I have no idea how to handle this
+      if (Start != End)
+      {
+	 cout << "Note, a broken or group was found in " << Pkg.Name() << "." << endl;
+	 Fail = true;
+	 break;
+      }
+            
+      // Upgrade the package if the candidate version will fix the problem.
+      if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
+      {
+	 PkgIterator P = Start.SmartTargetPkg();
+	 if (DoUpgrade(P) == false)
+	 {
+	    if (Debug == true)
+	       cout << "    Reinst Failed because of " << P.Name() << endl;
+	    Fail = true;
+	    break;
+	 }	 
+      }
+      else
+      {
+	 /* We let the algorithm deal with conflicts on its next iteration,
+	    it is much smarter than us */
+	 if (End->Type == pkgDEP_Conflicts)
+	    continue;
+	 
+	 if (Debug == true)
+	    cout << "    Reinst Failed early because of " << Start.TargetPkg().Name() << endl;
+	 Fail = true;
+	 break;
+      }      
+   }
+   
+   // Undo our operations - it might be smart to undo everything this did..
+   if (Fail == true)
+   {
+      if (WasKept == true)
+	 Cache.MarkKeep(Pkg);
+      else
+	 Cache.MarkDelete(Pkg);
+      return false;
+   }	 
+   
+   if (Debug == true)
+      cout << "  Re-Instated " << Pkg.Name() << endl;
+   return true;
+}
+									/*}}}*/
+// ProblemResolver::Resolve - Run the resolution pass			/*{{{*/
+// ---------------------------------------------------------------------
+/* This routines works by calculating a score for each package. The score
+   is derived by considering the package's priority and all reverse 
+   dependents giving an integer that reflects the amount of breakage that
+   adjusting the package will inflict. 
+      
+   It goes from highest score to lowest and corrects all of the breaks by 
+   keeping or removing the dependant packages. If that fails then it removes
+   the package itself and goes on. The routine should be able to intelligently
+   go from any broken state to a fixed state. 
+ 
+   The BrokenFix flag enables a mode where the algorithm tries to 
+   upgrade packages to advoid problems. */
+bool pkgProblemResolver::Resolve(bool BrokenFix)
+{
+ unsigned long Size = Cache.HeaderP->PackageCount;
+
+   // Record which packages are marked for install
+   bool Again = false;
+   do
+   {
+      Again = false;
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      {
+	 if (Cache[I].Install() == true)
+	    Flags[I->ID] |= PreInstalled;
+	 else
+	 {
+	    if (Cache[I].InstBroken() == true && BrokenFix == true)
+	    {
+	       Cache.MarkInstall(I,false);
+	       if (Cache[I].Install() == true)
+		  Again = true;
+	    }
+	    
+	    Flags[I->ID] &= ~PreInstalled;
+	 }
+	 Flags[I->ID] |= Upgradable;
+      }
+   }
+   while (Again == true);
+
+   if (Debug == true)
+      cout << "Starting" << endl;
+   
+   MakeScores();
+   
+   /* We have to order the packages so that the broken fixing pass 
+      operates from highest score to lowest. This prevents problems when
+      high score packages cause the removal of lower score packages that
+      would cause the removal of even lower score packages. */
+   pkgCache::Package **PList = new pkgCache::Package *[Size];
+   pkgCache::Package **PEnd = PList;
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      *PEnd++ = I;
+   This = this;
+   qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
+   
+/* for (pkgCache::Package **K = PList; K != PEnd; K++)
+      if (Scores[(*K)->ID] != 0)
+      {
+	 pkgCache::PkgIterator Pkg(Cache,*K);
+	 cout << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
+	    ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' << 
+	    Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
+      } */
+
+   if (Debug == true)
+      cout << "Starting 2" << endl;
+   
+   /* Now consider all broken packages. For each broken package we either
+      remove the package or fix it's problem. We do this once, it should
+      not be possible for a loop to form (that is a < b < c and fixing b by
+      changing a breaks c) */
+   bool Change = true;
+   for (int Counter = 0; Counter != 10 && Change == true; Counter++)
+   {
+      Change = false;
+      for (pkgCache::Package **K = PList; K != PEnd; K++)
+      {
+	 pkgCache::PkgIterator I(Cache,*K);
+
+	 /* We attempt to install this and see if any breaks result,
+	    this takes care of some strange cases */
+	 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
+	     I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
+	     (Flags[I->ID] & PreInstalled) != 0 &&
+	     (Flags[I->ID] & Protected) == 0)
+	 {
+	    if (Debug == true)
+	       cout << " Try to Re-Instate " << I.Name() << endl;
+	    int OldBreaks = Cache.BrokenCount();
+	    pkgCache::Version *OldVer = Cache[I].InstallVer;
+
+	    Cache.MarkInstall(I,false);
+	    if (Cache[I].InstBroken() == true || 
+		OldBreaks < Cache.BrokenCount())
+	    {
+	       if (OldVer == 0)
+		  Cache.MarkDelete(I);
+	       else
+		  Cache.MarkKeep(I);
+	    }	    
+	    else
+	       if (Debug == true)
+		  cout << "Re-Instated " << I.Name() << endl;
+	 }
+	    
+	 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
+	    continue;
+	 
+	 // Isolate the problem dependency
+	 PackageKill KillList[100];
+	 PackageKill *LEnd = KillList;
+	 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
+	 {
+	    // Compute a single dependency element (glob or)
+	    pkgCache::DepIterator Start = D;
+	    pkgCache::DepIterator End = D;
+	    unsigned char State = 0;
+	    for (bool LastOR = true; D.end() == false && LastOR == true; D++)
+	    {
+	       State |= Cache[D];
+	       LastOR = (D->CompareOp & pkgOP_OR) == pkgOP_OR;
+	       if (LastOR == true)
+		  End = D;
+	    }
+	    
+	    // We only worry about critical deps.
+	    if (End.IsCritical() != true)
+	       continue;
+	    
+	    // Dep is ok
+	    if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
+	       continue;
+	    
+	    // Hm, the group is broken.. I have no idea how to handle this
+	    if (Start != End)
+	    {
+	       cout << "Note, a broken or group was found in " << I.Name() << "." << endl;
+	       Cache.MarkDelete(I);
+	       break;
+	    }
+	    	    
+	    if (Debug == true)
+	       cout << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
+	    
+	    /* Conflicts is simple, decide if we should remove this package
+	       or the conflicted one */
+	    pkgCache::Version **VList = End.AllTargets();
+	    bool Done = false;
+	    for (pkgCache::Version **V = VList; *V != 0; V++)
+	    {
+	       pkgCache::VerIterator Ver(Cache,*V);
+	       pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+	    
+	       if (Debug == true)
+		  cout << "  Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] << 
+		  " as a solution to " << I.Name() << ' ' << (int)Scores[I->ID] << endl;
+	       if (Scores[I->ID] <= Scores[Pkg->ID] ||
+		   ((Cache[End] & pkgDepCache::DepGNow) == 0 &&
+		    End->Type != pkgDEP_Conflicts))
+	       {
+		  if ((Flags[I->ID] & Protected) != 0)
+		     continue;
+		  
+		  // See if a keep will do
+		  Cache.MarkKeep(I);
+		  if (Cache[I].InstBroken() == false)
+		  {
+		     if (Debug == true)
+			cout << "  Holding Back " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl;
+		  }		  
+		  else
+		  {
+		     if (BrokenFix == false || DoUpgrade(I) == false)
+		     {
+			if (Debug == true)
+			   cout << "  Removing " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl;
+			Cache.MarkDelete(I);
+			if (Counter > 1)
+			   Scores[I->ID] = Scores[Pkg->ID];
+		     }		     
+		  }
+
+		  Change = true;
+		  Done = true;
+		  break;
+	       }
+	       else
+	       {
+		  // Skip this if it is protected
+		  if ((Flags[Pkg->ID] & Protected) != 0)
+		     continue;
+		  
+		  LEnd->Pkg = Pkg;
+		  LEnd->Dep = End;
+		  LEnd++;
+		  if (End->Type != pkgDEP_Conflicts)
+		     break;
+	       }
+	    }
+
+	    // Hm, nothing can possibly satisify this dep. Nuke it.
+	    if (VList[0] == 0 && End->Type != pkgDEP_Conflicts)
+	    {
+	       Cache.MarkKeep(I);
+	       if (Cache[I].InstBroken() == false)
+	       {
+		  if (Debug == true)
+		     cout << "  Holding Back " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl;
+	       }	       
+	       else
+	       {
+		  if (Debug == true)
+		     cout << "  Removing " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl;
+		  Cache.MarkDelete(I);
+	       }
+
+	       Change = true;
+	       Done = true;
+	    }
+	    
+	    delete [] VList;
+	    if (Done == true)
+	       break;
+	 }
+	 
+	 // Apply the kill list now
+	 if (Cache[I].InstallVer != 0)
+	    for (PackageKill *J = KillList; J != LEnd; J++)
+         {
+	    Change = true;
+	    if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
+	    {
+	       if (J->Dep->Type == pkgDEP_Conflicts)
+	       {
+		  if (Debug == true)
+		     cout << "  Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl;
+		  Cache.MarkDelete(J->Pkg);
+	       }
+	    }
+	    else
+	    {
+	       if (Debug == true)
+		  cout << "  Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
+	       Cache.MarkKeep(J->Pkg);
+	    }
+	    
+	    if (Counter > 1)
+	       Scores[J->Pkg->ID] = Scores[I->ID];
+	 }      
+      }
+   }
+
+   if (Debug == true)
+      cout << "Done" << endl;
+   
+   delete [] Scores;
+   delete [] PList;
+   
+   if (Cache.BrokenCount() != 0)
+      return _error->Error("Internal error, ScoredFix generated breaks.");
+
+   return true;
+}
+									/*}}}*/
diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h
new file mode 100644
index 000000000..0dd77d940
--- /dev/null
+++ b/apt-pkg/algorithms.h
@@ -0,0 +1,91 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: algorithms.h,v 1.1 1998/07/07 04:17:00 jgg Exp $
+/* ######################################################################
+
+   Algorithms - A set of misc algorithms
+   
+   This simulate class displays what the ordering code has done and
+   analyses it with a fresh new dependency cache. In this way we can
+   see all of the effects of an upgrade run.
+
+   pkgDistUpgrade computes an upgrade that causes as many packages as
+   possible to move to the newest verison.
+   
+   pkgApplyStatus sets the target state based on the content of the status
+   field in the status file. It is important to get proper crash recovery.
+   
+   ##################################################################### */
+									/*}}}*/
+// Header section: pkglib
+#ifndef PKGLIB_ALGORITHMS_H
+#define PKGLIB_ALGORITHMS_H
+
+#ifdef __GNUG__
+#pragma interface "pkglib/algorithms.h"
+#endif 
+
+#include <pkglib/packagemanager.h>
+#include <pkglib/depcache.h>
+
+class pkgSimulate : public pkgPackageManager
+{
+   protected:
+
+   unsigned char *Flags;
+   
+   pkgDepCache Sim;
+   
+   // The Actuall installation implementation
+   virtual bool Install(PkgIterator Pkg,string File);
+   virtual bool Configure(PkgIterator Pkg);
+   virtual bool Remove(PkgIterator Pkg);
+   void ShortBreaks();
+   
+   public:
+
+   pkgSimulate(pkgDepCache &Cache);
+};
+
+class pkgProblemResolver
+{
+   pkgDepCache &Cache;
+   typedef pkgCache::PkgIterator PkgIterator;
+   typedef pkgCache::VerIterator VerIterator;
+   typedef pkgCache::DepIterator DepIterator;
+   typedef pkgCache::PrvIterator PrvIterator;
+   typedef pkgCache::Version Version;
+   typedef pkgCache::Package Package;
+   
+   enum Flags {Protected = (1 << 0), PreInstalled = (1 << 1),
+               Upgradable = (1 << 2)};
+   signed short *Scores;
+   unsigned char *Flags;
+   bool Debug;
+   
+   // Sort stuff
+   static pkgProblemResolver *This;
+   static int ScoreSort(const void *a,const void *b);
+
+   struct PackageKill
+   {
+      PkgIterator Pkg;
+      DepIterator Dep;
+   };
+
+   void MakeScores();
+   bool DoUpgrade(pkgCache::PkgIterator Pkg);
+   
+   public:
+   
+   inline void Protect(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= Protected;};
+   bool Resolve(bool BrokenFix = false);
+   
+   pkgProblemResolver(pkgDepCache &Cache);
+};
+
+bool pkgDistUpgrade(pkgDepCache &Cache);
+bool pkgApplyStatus(pkgDepCache &Cache);
+bool pkgFixBroken(pkgDepCache &Cache);
+
+#endif
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index f12491fe1..f234526db 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: cacheiterators.h,v 1.3 1998/07/05 05:33:52 jgg Exp $
+// $Id: cacheiterators.h,v 1.4 1998/07/07 04:17:00 jgg Exp $
 /* ######################################################################
    
    Cache Iterators - Iterators for navigating the cache structure
@@ -21,7 +21,8 @@
    The DepIterator can iterate over two lists, a list of 'version depends'
    or a list of 'package reverse depends'. The type is determined by the
    structure passed to the constructor, which should be the structure
-   that has the depends pointer as a member.
+   that has the depends pointer as a member. The provide iterator has the
+   same system.
    
    This header is not user includable, please use pkglib/pkgcache.h
    
@@ -31,6 +32,10 @@
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/cacheiterators.h"
+#endif 
+
 // Package Iterator
 class pkgCache::PkgIterator
 {
@@ -57,6 +62,7 @@ class pkgCache::PkgIterator
    inline Package const &operator *() const {return *Pkg;};
    inline operator Package *() {return Pkg == Owner->PkgP?0:Pkg;};
    inline operator Package const *() const {return Pkg == Owner->PkgP?0:Pkg;};
+   
    inline const char *Name() const {return Pkg->Name == 0?0:Owner->StrP + Pkg->Name;};
    inline const char *Section() const {return Pkg->Section == 0?0:Owner->StrP + Pkg->Section;};
    inline const char *TargetDist() const {return Pkg->TargetDist == 0?0:Owner->StrP + Pkg->TargetDist;};
@@ -111,13 +117,14 @@ class pkgCache::VerIterator
    inline Version const &operator *() const {return *Ver;};
    inline operator Version *() {return Ver == Owner.VerP?0:Ver;};
    inline operator Version const *() const {return Ver == Owner.VerP?0:Ver;};
+
    inline const char *VerStr() const {return Ver->VerStr == 0?0:Owner.StrP + Ver->VerStr;};
    inline const char *Section() const {return Ver->Section == 0?0:Owner.StrP + Ver->Section;};
    inline PkgIterator ParentPkg() const {return PkgIterator(Owner,Owner.PkgP + Ver->ParentPkg);};
    inline DepIterator DependsList() const;
    inline PrvIterator ProvidesList() const;
-   inline unsigned long Index() const {return Ver - Owner.VerP;};
    inline VerFileIterator FileList() const;
+   inline unsigned long Index() const {return Ver - Owner.VerP;};
 
    inline VerIterator(pkgCache &Owner,Version *Trg = 0) : Ver(Trg), Owner(Owner) 
    { 
@@ -154,16 +161,17 @@ class pkgCache::DepIterator
    inline Dependency const &operator *() const {return *Dep;};
    inline operator Dependency *() {return Dep == Owner->DepP?0:Dep;};
    inline operator Dependency const *() const {return Dep == Owner->DepP?0:Dep;};
+   
    inline const char *TargetVer() const {return Dep->Version == 0?0:Owner->StrP + Dep->Version;};
    inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + Dep->Package);};
-   Version **AllTargets();   
-   bool SmartTargetPkg(PkgIterator &Result);
    inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner);SmartTargetPkg(R);return R;};
    inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + Dep->ParentVer);};
    inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Dep->ParentVer].ParentPkg);};
-   bool IsCritical();
    inline bool Reverse() {return Type == DepRev;};
    inline unsigned long Index() const {return Dep - Owner->DepP;};
+   bool IsCritical();
+   Version **AllTargets();   
+   bool SmartTargetPkg(PkgIterator &Result);
       
    inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
           Dep(Trg), Type(DepVer), Owner(&Owner) 
@@ -208,6 +216,7 @@ class pkgCache::PrvIterator
    inline Provides const &operator *() const {return *Prv;};
    inline operator Provides *() {return Prv == Owner->ProvideP?0:Prv;};
    inline operator Provides const *() const {return Prv == Owner->ProvideP?0:Prv;};
+
    inline const char *Name() const {return Owner->StrP + Owner->PkgP[Prv->ParentPkg].Name;};
    inline const char *ProvideVersion() const {return Prv->ProvideVersion == 0?0:Owner->StrP + Prv->ProvideVersion;};
    inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Prv->ParentPkg);};
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
new file mode 100644
index 000000000..6d937d657
--- /dev/null
+++ b/apt-pkg/contrib/configuration.cc
@@ -0,0 +1,137 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: configuration.cc,v 1.1 1998/07/07 04:17:10 jgg Exp $
+/* ######################################################################
+
+   Configuration Class
+   
+   This class provides a configuration file and command line parser
+   for a tree-oriented configuration environment. All runtime configuration
+   is stored in here.
+   
+   ##################################################################### */
+									/*}}}*/
+// Include files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/configuration.h"
+#endif
+#include <pkglib/configuration.h>
+#include <strutl.h>
+
+#include <stdio.h>
+									/*}}}*/
+Configuration *_config;
+
+// Configuration::Configuration - Constructor				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+Configuration::Configuration()
+{
+   Root = new Item;
+}
+									/*}}}*/
+// Configuration::Lookup - Lookup a single item									/*{{{*/
+// ---------------------------------------------------------------------
+/* This will lookup a single item by name below another item. It is a 
+   helper function for the main lookup function */
+Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
+					   unsigned long Len,bool Create)
+{
+   int Res = 1;
+   Item *I = Head->Child;
+   Item **Last = &Head->Child;
+   for (; I != 0; Last = &I->Next, I = I->Next)
+      if ((Res = stringcasecmp(I->Value.begin(),I->Value.end(),S,S + Len)) == 0)
+	 break;
+
+   if (Res == 0)
+      return I;
+   if (Create == false)
+      return 0;
+   
+   I = new Item;
+   I->Value = string(S,Len);
+   I->Next = *Last;
+   *Last = I;
+   return I;
+}
+									/*}}}*/
+// Configuration::Lookup - Lookup a fully scoped item			/*{{{*/
+// ---------------------------------------------------------------------
+/* This performs a fully scoped lookup of a given name, possibly creating
+   new items */
+Configuration::Item *Configuration::Lookup(const char *Name,bool Create)
+{
+   const char *Start = Name;
+   const char *End = Start + strlen(Name);
+   const char *TagEnd = Name;
+   Item *Itm = Root;
+   for (; End - TagEnd > 2; TagEnd++)
+   {
+      if (TagEnd[0] == ':' && TagEnd[1] == ':')
+      {
+	 Itm = Lookup(Itm,Start,TagEnd - Start,Create);
+	 if (Itm == 0)
+	    return 0;
+	 TagEnd = Start = TagEnd + 2;	 
+      }
+   }   
+
+   Itm = Lookup(Itm,Start,End - Start,Create);
+   if (Itm == 0)
+      return 0;
+   return Itm;
+}
+									/*}}}*/
+// Configuration::Find - Find a value					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string Configuration::Find(const char *Name,const char *Default)
+{
+   Item *Itm = Lookup(Name,false);
+   if (Itm == 0 || Itm->Value.empty() == true)
+      return Default;
+   return Itm->Value;
+}
+									/*}}}*/
+// Configuration::FindI - Find an integer value				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int Configuration::FindI(const char *Name,int Default)
+{
+   Item *Itm = Lookup(Name,false);
+   if (Itm == 0 || Itm->Value.empty() == true)
+      return Default;
+   
+   char *End;
+   int Res = strtol(Itm->Value.c_str(),&End,0);
+   if (End == Itm->Value.c_str())
+      return Default;
+   
+   return Res;
+}
+									/*}}}*/
+// Configuration::Set - Set a value					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::Set(const char *Name,string Value)
+{
+   Item *Itm = Lookup(Name,true);
+   if (Itm == 0)
+      return;
+   Itm->Value = Value;
+}
+									/*}}}*/
+// Configuration::Set - Set an integer value				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::Set(const char *Name,int Value)
+{
+   Item *Itm = Lookup(Name,true);
+   if (Itm == 0)
+      return;
+   char S[300];
+   snprintf(S,sizeof(S),"%i",Value);
+   Itm->Value = S;
+}
+									/*}}}*/
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
new file mode 100644
index 000000000..7476346ef
--- /dev/null
+++ b/apt-pkg/contrib/configuration.h
@@ -0,0 +1,61 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: configuration.h,v 1.1 1998/07/07 04:17:10 jgg Exp $
+/* ######################################################################
+
+   Configuration Class
+   
+   This class provides a configuration file and command line parser
+   for a tree-oriented configuration environment. All runtime configuration
+   is stored in here.
+   
+   Each configuration name is given as a fully scoped string such as
+     Foo::Bar
+   And has associated with it a text string. The Configuration class only
+   provides storage and lookup for this tree, other classes provide
+   configuration file formats (and parsers/emitters if needed).
+   
+   Most things can get by quite happily with,
+     cout << _config->Find("Foo::Bar") << endl;
+   
+   ##################################################################### */
+									/*}}}*/
+// Header section: pkglib
+#ifndef PKGLIB_TAGFILE_H
+#define PKGLIB_TAGFILE_H
+
+#ifdef __GNUG__
+#pragma interface "pkglib/configuration.h"
+#endif 
+
+#include <string>
+
+class Configuration
+{
+   struct Item
+   {
+      string Value;
+      string Tag;
+      Item *Child;
+      Item *Next;
+      Item() : Child(0), Next(0) {};
+   };
+   Item *Root;
+   
+   Item *Lookup(Item *Head,const char *S,unsigned long Len,bool Create);
+   Item *Lookup(const char *Name,bool Create);
+      
+   public:
+
+   string Find(const char *Name,const char *Default = 0);
+   int FindI(const char *Name,int Default = 0);
+   
+   void Set(const char *Name,string Value);
+   void Set(const char *Name,int Value);
+
+   Configuration();
+};
+
+extern Configuration *_config;
+
+#endif
diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc
index 59d2b8c8b..d1ea1b87b 100644
--- a/apt-pkg/contrib/error.cc
+++ b/apt-pkg/contrib/error.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: error.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $
+// $Id: error.cc,v 1.2 1998/07/07 04:17:10 jgg Exp $
 /* ######################################################################
    
    Global Erorr Class - Global error mechanism
@@ -14,6 +14,10 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/error.h"
+#endif 
+
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
@@ -27,7 +31,7 @@ GlobalError *_error = new GlobalError;
 // GlobalError::GlobalError - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-GlobalError::GlobalError() : PendingFlag(false)
+GlobalError::GlobalError() : List(0), PendingFlag(false)
 {
 }
 									/*}}}*/
@@ -49,10 +53,10 @@ bool GlobalError::Errno(const char *Function,const char *Description,...)
    sprintf(S + strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
 
    // Put it on the list
-   Item Itm;
-   Itm.Text = S;
-   Itm.Error = true;
-   List.push_back(Itm);
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = true;
+   Insert(Itm);
    
    PendingFlag = true;
 
@@ -72,10 +76,10 @@ bool GlobalError::Error(const char *Description,...)
    vsprintf(S,Description,args);
 
    // Put it on the list
-   Item Itm;
-   Itm.Text = S;
-   Itm.Error = true;
-   List.push_back(Itm);
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = true;
+   Insert(Itm);
    
    PendingFlag = true;
    
@@ -95,10 +99,10 @@ bool GlobalError::Warning(const char *Description,...)
    vsprintf(S,Description,args);
 
    // Put it on the list
-   Item Itm;
-   Itm.Text = S;
-   Itm.Error = false;
-   List.push_back(Itm);
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = false;
+   Insert(Itm);
    
    return false;
 }
@@ -109,12 +113,17 @@ bool GlobalError::Warning(const char *Description,...)
    true if the message is an error. */
 bool GlobalError::PopMessage(string &Text)
 {
-   bool Ret = List.front().Error;
-   Text = List.front().Text;
-   List.erase(List.begin());
-
+   if (List == 0)
+      return false;
+      
+   bool Ret = List->Error;
+   Text = List->Text;
+   Item *Old = List;
+   List = List->Next;
+   delete Old;
+   
    // This really should check the list to see if only warnings are left..
-   if (empty())
+   if (List == 0)
       PendingFlag = false;
    
    return Ret;
@@ -137,3 +146,30 @@ void GlobalError::DumpErrors()
    }
 }
 									/*}}}*/
+// GlobalError::Discard - Discard									/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::Discard()
+{
+   while (List != 0)
+   {
+      Item *Old = List;
+      List = List->Next;
+      delete Old;
+   }
+   
+   PendingFlag = false;
+};
+									/*}}}*/
+// GlobalError::Insert - Insert a new item at the end			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::Insert(Item *Itm)
+{
+   Item **End = &List;
+   for (Item *I = List; I != 0; I = I->Next)
+      End = &I->Next;
+   Itm->Next = *End;
+   *End = Itm;
+}
+									/*}}}*/
diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h
index 06b998e5e..06367592b 100644
--- a/apt-pkg/contrib/error.h
+++ b/apt-pkg/contrib/error.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: error.h,v 1.1 1998/07/02 02:58:13 jgg Exp $
+// $Id: error.h,v 1.2 1998/07/07 04:17:11 jgg Exp $
 /* ######################################################################
    
    Global Erorr Class - Global error mechanism
@@ -41,8 +41,11 @@
 #ifndef PKGLIB_ERROR_H
 #define PKGLIB_ERROR_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/error.h"
+#endif 
+
 #include <string>
-#include <vector.h>
 
 class GlobalError
 {
@@ -50,10 +53,12 @@ class GlobalError
    {
       string Text;
       bool Error;
+      Item *Next;
    };
    
-   vector<Item> List;
+   Item *List;
    bool PendingFlag;
+   void Insert(Item *I);
    
    public:
 
@@ -67,9 +72,9 @@ class GlobalError
 
    // Simple accessors
    inline bool PendingError() {return PendingFlag;};
-   inline bool empty() {return List.empty();};
+   inline bool empty() {return List == 0;};
    bool PopMessage(string &Text);
-   void Discard() {List.erase(List.begin(),List.end()); PendingFlag = false;};
+   void Discard();
 
    // Usefull routine to dump to cerr
    void DumpErrors();
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 6c6441ef6..29b12bef1 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: fileutl.cc,v 1.2 1998/07/04 05:57:41 jgg Exp $
+// $Id: fileutl.cc,v 1.3 1998/07/07 04:17:12 jgg Exp $
 /* ######################################################################
    
    File Utilities
@@ -14,6 +14,9 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/fileutl.h"
+#endif 
 #include <pkglib/fileutl.h>
 #include <pkglib/error.h>
 
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 1b6666843..aa2d2ee2e 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: fileutl.h,v 1.1 1998/07/02 02:58:13 jgg Exp $
+// $Id: fileutl.h,v 1.2 1998/07/07 04:17:13 jgg Exp $
 /* ######################################################################
    
    File Utilities
@@ -22,6 +22,10 @@
 #ifndef PKGLIB_FILEUTL_H
 #define PKGLIB_FILEUTL_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/fileutl.h"
+#endif 
+
 #include <string>
 
 class File
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index 41ea02aec..c0cc13f00 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: mmap.cc,v 1.3 1998/07/04 22:32:15 jgg Exp $
+// $Id: mmap.cc,v 1.4 1998/07/07 04:17:14 jgg Exp $
 /* ######################################################################
    
    MMap Class - Provides 'real' mmap or a faked mmap using read().
@@ -21,6 +21,10 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/mmap.h"
+#endif 
+
 #define _BSD_SOURCE
 #include <pkglib/mmap.h>
 #include <pkglib/error.h>
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index c7ddf685d..55feda741 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: mmap.h,v 1.2 1998/07/04 05:57:43 jgg Exp $
+// $Id: mmap.h,v 1.3 1998/07/07 04:17:15 jgg Exp $
 /* ######################################################################
    
    MMap Class - Provides 'real' mmap or a faked mmap using read().
@@ -26,6 +26,10 @@
 #ifndef PKGLIB_MMAP_H
 #define PKGLIB_MMAP_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/mmap.h"
+#endif
+
 #include <string>
 #include <pkglib/fileutl.h>
 
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
new file mode 100644
index 000000000..14965f91e
--- /dev/null
+++ b/apt-pkg/contrib/strutl.cc
@@ -0,0 +1,343 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: strutl.cc,v 1.1 1998/07/07 04:17:16 jgg Exp $
+/* ######################################################################
+
+   String Util - Some usefull string functions.
+
+   strstrip - Remove whitespace from the front and end of a line.
+   
+   This source is placed in the Public Domain, do with it what you will
+   It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>   
+   
+   ##################################################################### */
+									/*}}}*/
+// Includes								/*{{{*/
+#include <strutl.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+									/*}}}*/
+
+// strstrip - Remove white space from the front and back of a string	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is handy to use when parsing a file. It also removes \n's left 
+   over from fgets and company */
+char *_strstrip(char *String)
+{
+   for (;*String != 0 && (*String == ' ' || *String == '\t'); String++);
+
+   if (*String == 0)
+      return String;
+
+   char *End = String + strlen(String) - 1;
+   for (;End != String - 1 && (*End == ' ' || *End == '\t' || *End == '\n' ||
+			       *End == '\r'); End--);
+   End++;
+   *End = 0;
+   return String;
+};
+									/*}}}*/
+// strtabexpand - Converts tabs into 8 spaces				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+char *_strtabexpand(char *String,size_t Len)
+{
+   for (char *I = String; I != I + Len && *I != 0; I++)
+   {
+      if (*I != '\t')
+	 continue;
+      if (I + 8 > String + Len)
+      {
+	 *I = 0;
+	 return String;
+      }
+
+      /* Assume the start of the string is 0 and find the next 8 char
+         division */
+      int Len;
+      if (String == I)
+	 Len = 1;
+      else
+	 Len = 8 - ((String - I) % 8);
+      Len -= 2;
+      if (Len <= 0)
+      {
+	 *I = ' ';
+	 continue;
+      }
+      
+      memmove(I + Len,I + 1,strlen(I) + 1);
+      for (char *J = I; J + Len != I; *I = ' ', I++);
+   }
+   return String;
+}
+									/*}}}*/
+// ParseQuoteWord - Parse a single word out of a string			/*{{{*/
+// ---------------------------------------------------------------------
+/* This grabs a single word, converts any % escaped characters to their
+   proper values and advances the pointer. Double quotes are understood
+   and striped out as well. */
+bool ParseQuoteWord(const char *&String,string &Res)
+{
+   // Skip leading whitespace
+   const char *C = String;
+   for (;*C != 0 && *C == ' '; C++);
+   if (*C == 0)
+      return false;
+   
+   // Jump to the next word
+   for (;*C != 0 && *C != ' '; C++)
+   {
+      if (*C == '"')
+      {
+	 for (C++;*C != 0 && *C != '"'; C++);
+	 if (*C == 0)
+	    return false;
+      }
+   }
+
+   // Now de-quote characters
+   char Buffer[1024];
+   char Tmp[3];
+   const char *Start = String;
+   char *I;
+   for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++)
+   {
+      if (*Start == '%' && Start + 2 < C)
+      {
+	 Tmp[0] = Start[1];
+	 Tmp[1] = Start[2];
+	 Tmp[3] = 0;
+	 *I = (char)strtol(Tmp,0,16);
+	 Start += 3;
+	 continue;
+      }
+      if (*Start != '"')
+	 *I = *Start;
+      else
+	 I--;
+      Start++;
+   }
+   *I = 0;
+   Res = Buffer;
+   
+   // Skip ending white space
+   for (;*C != 0 && *C == ' '; C++);
+   String = C;
+   return true;
+}
+									/*}}}*/
+// QuoteString - Convert a string into quoted from			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string QuoteString(string Str,const char *Bad)
+{
+   string Res;
+   for (string::iterator I = Str.begin(); I != Str.end(); I++)
+   {
+      if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || 
+	  *I <= 0x20 || *I >= 0x7F)
+      {
+	 char Buf[10];
+	 sprintf(Buf,"%%%02x",(int)*I);
+	 Res += Buf;
+      }
+      else
+	 Res += *I;
+   }
+   return Res;
+}
+									/*}}}*/
+// SizeToStr - Convert a long into a human readable size		/*{{{*/
+// ---------------------------------------------------------------------
+/* A max of 4 digits are shown before conversion to the next highest unit. The
+   max length of the string will be 5 chars unless the size is > 10 
+   YottaBytes (E24) */
+string SizeToStr(double Size)
+{
+   char S[300];
+   double ASize;
+   if (Size >= 0)
+      ASize = Size;
+   else
+      ASize = -1*Size;
+   
+   /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, 
+      ExaBytes, ZettaBytes, YottaBytes */
+   char Ext[] = {'b','k','M','G','T','P','E','Z','Y'};
+   int I = 0;
+   while (I <= 8)
+   {
+      if (ASize < 100 && I != 0)
+      {
+         sprintf(S,"%.1f%c",ASize,Ext[I]);
+	 break;
+      }
+      
+      if (ASize < 10000)
+      {
+         sprintf(S,"%.0f%c",ASize,Ext[I]);
+	 break;
+      }
+      ASize /= 1000.0;
+      I++;
+   }
+   
+   return S;
+}
+									/*}}}*/
+// TimeToStr - Convert the time into a string				/*{{{*/
+// ---------------------------------------------------------------------
+/* Converts a number of seconds to a hms format */
+string TimeToStr(unsigned long Sec)
+{
+   char S[300];
+   
+   while (1)
+   {
+      if (Sec > 60*60*24)
+      {
+	 sprintf(S,"%lid %lih%lim%lis",Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
+	 break;
+      }
+      
+      if (Sec > 60*60)
+      {
+	 sprintf(S,"%lih%lim%lis",Sec/60/60,(Sec/60) % 60,Sec % 60);
+	 break;
+      }
+      
+      if (Sec > 60)
+      {
+	 sprintf(S,"%lim%lis",Sec/60,Sec % 60);
+	 break;
+      }
+      
+      sprintf(S,"%lis",Sec);
+      break;
+   }
+   
+   return S;
+}
+									/*}}}*/
+// SubstVar - Substitute a string for another string			/*{{{*/
+// ---------------------------------------------------------------------
+/* This replaces all occurances of Subst with Contents in Str. */
+string SubstVar(string Str,string Subst,string Contents)
+{
+   string::size_type Pos;
+   string::size_type OldPos = 0;
+   string Temp;
+   
+   while (OldPos < Str.length() && 
+	  (Pos = Str.find(Subst,OldPos)) != string::npos)
+   {
+      Temp += string(Str,OldPos,Pos) + Contents;
+      OldPos = Pos + Subst.length();      
+   }
+   
+   if (OldPos == 0)
+      return Str;
+   
+   return Temp + string(Str,OldPos);
+}
+									/*}}}*/
+// Base64Encode - Base64 Encoding routine for short strings		/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine performs a base64 transformation on a string. It was ripped
+   from wget and then patched and bug fixed.
+ 
+   This spec can be found in rfc2045 */
+string Base64Encode(string S)
+{
+   // Conversion table.
+   static char tbl[64] = {'A','B','C','D','E','F','G','H',
+   			  'I','J','K','L','M','N','O','P',
+                          'Q','R','S','T','U','V','W','X',
+                          'Y','Z','a','b','c','d','e','f',
+                          'g','h','i','j','k','l','m','n',
+                          'o','p','q','r','s','t','u','v',
+                          'w','x','y','z','0','1','2','3',
+                          '4','5','6','7','8','9','+','/'};
+   
+   // Pre-allocate some space
+   string Final;
+   Final.reserve((4*S.length() + 2)/3 + 2);
+
+   /* Transform the 3x8 bits to 4x6 bits, as required by
+      base64.  */
+   for (string::const_iterator I = S.begin(); I < S.end(); I += 3)
+   {
+      char Bits[3] = {0,0,0};
+      Bits[0] = I[0];
+      if (I + 1 < S.end())
+	 Bits[1] = I[1];
+      if (I + 2 < S.end())
+	 Bits[2] = I[2];
+
+      Final += tbl[Bits[0] >> 2];
+      Final += tbl[((Bits[0] & 3) << 4) + (Bits[1] >> 4)];
+      
+      if (I + 1 >= S.end())
+	 break;
+      
+      Final += tbl[((Bits[1] & 0xf) << 2) + (Bits[2] >> 6)];
+      
+      if (I + 2 >= S.end())
+	 break;
+      
+      Final += tbl[Bits[2] & 0x3f];
+   }
+
+   /* Apply the padding elements, this tells how many bytes the remote
+      end should discard */
+   if (S.length() % 3 == 2)
+      Final += '=';
+   if (S.length() % 3 == 1)
+      Final += "==";
+   
+   return Final;
+}
+									/*}}}*/
+// stringcmp - Arbitary string compare					/*{{{*/
+// ---------------------------------------------------------------------
+/* This safely compares two non-null terminated strings of arbitary 
+   length */
+int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
+{
+   for (; A != AEnd && B != BEnd; A++, B++)
+      if (*A != *B)
+	 break;
+   
+   if (A == AEnd && B == BEnd)
+      return 0;
+   if (A == AEnd)
+      return 1;
+   if (B == BEnd)
+      return -1;
+   if (*A < *B)
+      return -1;
+   return 1;
+}
+									/*}}}*/
+// stringcasecmp - Arbitary case insensitive string compare		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
+{
+   for (; A != AEnd && B != BEnd; A++, B++)
+      if (toupper(*A) != toupper(*B))
+	 break;
+   
+   if (A == AEnd && B == BEnd)
+      return 0;
+   if (A == AEnd)
+      return 1;
+   if (B == BEnd)
+      return -1;
+   if (toupper(*A) < toupper(*B))
+      return -1;
+   return 1;
+}
+									/*}}}*/
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
new file mode 100644
index 000000000..44a10c2f3
--- /dev/null
+++ b/apt-pkg/contrib/strutl.h
@@ -0,0 +1,36 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: strutl.h,v 1.1 1998/07/07 04:17:16 jgg Exp $
+/* ######################################################################
+
+   String Util - These are some usefull string functions
+   
+   _strstrip is a function to remove whitespace from the front and end
+   of a string.
+   
+   This source is placed in the Public Domain, do with it what you will
+   It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>   
+   
+   ##################################################################### */
+									/*}}}*/
+// This is a private header
+// Header section: /
+#ifndef STRUTL_H
+#define STRUTL_H
+
+#include <stdlib.h>
+#include <string>
+
+char *_strstrip(char *String);
+char *_strtabexpand(char *String,size_t Len);
+bool ParseQuoteWord(const char *&String,string &Res);
+string QuoteString(string Str,const char *Bad);
+string SizeToStr(double Bytes);
+string TimeToStr(unsigned long Sec);
+string SubstVar(string Str,string Subst,string Contents);
+string Base64Encode(string Str);
+
+int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
+int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
+
+#endif
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index 4c37eb775..5fbb43a9f 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: deblistparser.cc,v 1.3 1998/07/05 05:34:00 jgg Exp $
+// $Id: deblistparser.cc,v 1.4 1998/07/07 04:17:16 jgg Exp $
 /* ######################################################################
    
    Package Cache Generator - Generator for the cache structure.
@@ -147,27 +147,27 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
    const char *Stop;
    if (Section.Find("Priority",Start,Stop) == true)
    {
-      WordList PrioList[] = {{"important",pkgCache::Important},
-	                     {"required",pkgCache::Required},
-	                     {"standard",pkgCache::Standard},
-                             {"optional",pkgCache::Optional},
-                             {"extra",pkgCache::Extra}};
+      WordList PrioList[] = {{"important",pkgCache::State::Important},
+	                     {"required",pkgCache::State::Required},
+	                     {"standard",pkgCache::State::Standard},
+	                     {"optional",pkgCache::State::Optional},
+	                     {"extra",pkgCache::State::Extra}};
       if (GrabWord(string(Start,Stop-Start),PrioList,
 		   _count(PrioList),Ver->Priority) == false)
 	 return _error->Error("Malformed Priority line");
    }
 
-   if (ParseDepends(Ver,"Depends",pkgCache::Depends) == false)
+   if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
       return false;
-   if (ParseDepends(Ver,"PreDepends",pkgCache::PreDepends) == false)
+   if (ParseDepends(Ver,"PreDepends",pkgCache::Dep::PreDepends) == false)
       return false;
-   if (ParseDepends(Ver,"Suggests",pkgCache::Suggests) == false)
+   if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
       return false;
-   if (ParseDepends(Ver,"Recommends",pkgCache::Recommends) == false)
+   if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
       return false;
-   if (ParseDepends(Ver,"Conflicts",pkgCache::Conflicts) == false)
+   if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
       return false;
-   if (ParseDepends(Ver,"Replaces",pkgCache::Depends) == false)
+   if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Depends) == false)
       return false;
 
    if (ParseProvides(Ver) == false)
@@ -186,9 +186,9 @@ bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
    if (Pkg->Section == 0)
       if ((Pkg->Section = UniqFindTagWrite("Section")) == 0)
 	 return false;
-   if (HandleFlag("Essential",Pkg->Flags,pkgCache::Essential) == false)
+   if (HandleFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
       return false;
-   if (HandleFlag("Immediate-Configure",Pkg->Flags,pkgCache::ImmediateConf) == false)
+   if (HandleFlag("Immediate-Configure",Pkg->Flags,pkgCache::Flag::ImmediateConf) == false)
       return false;
    if (ParseStatus(Pkg,Ver) == false)
       return false;
@@ -223,11 +223,11 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
       return _error->Error("Malformed Status line");
 
    // Process the want field
-   WordList WantList[] = {{"unknown",pkgCache::Unknown},
-                          {"install",pkgCache::Install},
-                          {"hold",pkgCache::Hold},
-                          {"deinstall",pkgCache::DeInstall},
-                          {"purge",pkgCache::Purge}};
+   WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
+                          {"install",pkgCache::State::Install},
+                          {"hold",pkgCache::State::Hold},
+                          {"deinstall",pkgCache::State::DeInstall},
+                          {"purge",pkgCache::State::Purge}};
    if (GrabWord(string(Start,I-Start),WantList,
 		_count(WantList),Pkg->SelectedState) == false)
       return _error->Error("Malformed 1st word in the Status line");
@@ -240,10 +240,10 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
       return _error->Error("Malformed status line, no 2nd word");
 
    // Process the flag field
-   WordList FlagList[] = {{"ok",pkgCache::Ok},
-                          {"reinstreq",pkgCache::ReInstReq},
-                          {"hold",pkgCache::HoldInst},
-                          {"hold-reinstreq",pkgCache::HoldReInstReq}};
+   WordList FlagList[] = {{"ok",pkgCache::State::Ok},
+                          {"reinstreq",pkgCache::State::ReInstReq},
+                          {"hold",pkgCache::State::HoldInst},
+                          {"hold-reinstreq",pkgCache::State::HoldReInstReq}};
    if (GrabWord(string(Start,I-Start),FlagList,
 		_count(FlagList),Pkg->InstState) == false)
       return _error->Error("Malformed 2nd word in the Status line");
@@ -256,15 +256,15 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
       return _error->Error("Malformed Status line, no 3rd word");
 
    // Process the flag field
-   WordList StatusList[] = {{"not-installed",pkgCache::NotInstalled},
-                            {"unpacked",pkgCache::UnPacked},
-                            {"half-configured",pkgCache::HalfConfigured},
-                            {"installed",pkgCache::Installed},
-                            {"uninstalled",pkgCache::UnInstalled},
-                            {"half-installed",pkgCache::HalfInstalled},
-                            {"config-files",pkgCache::ConfigFiles},
-                            {"post-inst-failed",pkgCache::HalfConfigured},
-                            {"removal-failed",pkgCache::HalfInstalled}};
+   WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
+                            {"unpacked",pkgCache::State::UnPacked},
+                            {"half-configured",pkgCache::State::HalfConfigured},
+                            {"installed",pkgCache::State::Installed},
+                            {"uninstalled",pkgCache::State::UnInstalled},
+                            {"half-installed",pkgCache::State::HalfInstalled},
+                            {"config-files",pkgCache::State::ConfigFiles},
+                            {"post-inst-failed",pkgCache::State::HalfConfigured},
+                            {"removal-failed",pkgCache::State::HalfInstalled}};
    if (GrabWord(string(Start,I-Start),StatusList,
 		_count(StatusList),Pkg->CurrentState) == false)
       return _error->Error("Malformed 3rd word in the Status line");
@@ -273,8 +273,8 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
       version as well. Only if it is actually installed.. Otherwise
       the interesting dpkg handling of the status file creates bogus 
       entries. */
-   if (!(Pkg->CurrentState == pkgCache::NotInstalled ||
-	 Pkg->CurrentState == pkgCache::ConfigFiles))
+   if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
+	 Pkg->CurrentState == pkgCache::State::ConfigFiles))
    {
       if (Ver.end() == true)
 	 _error->Warning("Encountered status field in a non-version description");
@@ -330,19 +330,19 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
 	 if (*I == '=')
 	 {
 	    I++;
-	    Op = pkgCache::LessEq;
+	    Op = pkgCache::Dep::LessEq;
 	    break;
 	 }
 	 
 	 if (*I == '<')
 	 {
 	    I++;
-	    Op = pkgCache::Less;
+	    Op = pkgCache::Dep::Less;
 	    break;
 	 }
 	 
 	 // < is the same as <= and << is really Cs < for some reason
-	 Op = pkgCache::LessEq;
+	 Op = pkgCache::Dep::LessEq;
 	 break;
 	 
 	 case '>':
@@ -350,29 +350,29 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
 	 if (*I == '=')
 	 {
 	    I++;
-	    Op = pkgCache::GreaterEq;
+	    Op = pkgCache::Dep::GreaterEq;
 	    break;
 	 }
 	 
 	 if (*I == '>')
 	 {
 	    I++;
-	    Op = pkgCache::Greater;
+	    Op = pkgCache::Dep::Greater;
 	    break;
 	 }
 	 
 	 // > is the same as >= and >> is really Cs > for some reason
-	 Op = pkgCache::GreaterEq;
+	 Op = pkgCache::Dep::GreaterEq;
 	 break;
 	 
 	 case '=':
-	 Op = pkgCache::Equals;
+	 Op = pkgCache::Dep::Equals;
 	 I++;
 	 break;
 	 
 	 // HACK around bad package definitions
 	 default:
-	 Op = pkgCache::Equals;
+	 Op = pkgCache::Dep::Equals;
 	 break;
       }
       
@@ -389,13 +389,13 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
    else
    {
       Ver = string();
-      Op = pkgCache::NoOp;
+      Op = pkgCache::Dep::NoOp;
    }
    
    // Skip whitespace
    for (;I != Stop && isspace(*I) != 0; I++);
    if (I != Stop && *I == '|')
-      Op |= pkgCache::Or;
+      Op |= pkgCache::Dep::Or;
    
    if (I == Stop || *I == ',' || *I == '|')
    {
@@ -453,7 +453,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
       Start = ParseDepends(Start,Stop,Package,Version,Op);
       if (Start == 0)
 	 return _error->Error("Problem parsing Provides line");
-      if (Op != pkgCache::NoOp)
+      if (Op != pkgCache::Dep::NoOp)
 	 return _error->Error("Malformed provides line");
 
       if (NewProvides(Ver,Package,Version) == false)
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
new file mode 100644
index 000000000..a7784c0a5
--- /dev/null
+++ b/apt-pkg/depcache.cc
@@ -0,0 +1,903 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: depcache.cc,v 1.1 1998/07/07 04:17:01 jgg Exp $
+/* ######################################################################
+
+   Dependency Cache - Caches Dependency information.
+   
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/depcache.h"
+#endif
+#include <pkglib/depcache.h>
+
+#include <pkglib/version.h>
+#include <pkglib/error.h>
+									/*}}}*/
+
+// DepCache::pkgDepCache - Constructors					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgDepCache::pkgDepCache(MMap &Map) :
+             pkgCache(Map), PkgState(0), DepState(0) 
+{
+   if (_error->PendingError() == false)
+      Init();
+}
+									/*}}}*/
+// DepCache::~pkgDepCache - Destructor					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgDepCache::~pkgDepCache()
+{
+   delete [] PkgState;
+   delete [] DepState;
+}
+									/*}}}*/
+// DepCache::ReMap - Regenerate the extra data for the new cache	/*{{{*/
+// ---------------------------------------------------------------------
+/* pkgCache's constructors call this function, but because the object is not
+   fully constructed at that point it will not result in this function being
+   called but pkgCache::ReMap will be instead.*/
+bool pkgDepCache::ReMap()
+{
+   if (pkgCache::ReMap() == false)
+      return false;
+   
+   return Init();
+}
+									/*}}}*/
+// DepCache::Init - Generate the initial extra structures.		/*{{{*/
+// ---------------------------------------------------------------------
+/* This allocats the extension buffers and initializes them. */
+bool pkgDepCache::Init()
+{
+   delete [] PkgState;
+   delete [] DepState;
+   PkgState = new StateCache[Head().PackageCount];
+   DepState = new unsigned char[Head().DependsCount];
+   memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount);
+   memset(DepState,0,sizeof(*DepState)*Head().DependsCount); 
+   
+   /* Set the current state of everything. In this state all of the
+      packages are kept exactly as is. See AllUpgrade */
+   for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+   {
+      // Find the proper cache slot
+      StateCache &State = PkgState[I->ID];
+      State.iFlags = 0;
+      
+      // Figure out the install version
+      State.CandidateVer = GetCandidateVer(I);
+      State.InstallVer = I.CurrentVer();
+      State.Mode = ModeKeep;
+      
+      State.Update(I,*this);
+   }   
+   
+   Update();
+   
+   return true;
+} 
+									/*}}}*/
+// DepCache::GetCandidateVer - Returns the Candidate install version	/*{{{*/
+// ---------------------------------------------------------------------
+/* The default just returns the target version if it exists or the
+   highest version. */
+pkgDepCache::VerIterator pkgDepCache::GetCandidateVer(PkgIterator Pkg)
+{
+   // Try to use an explicit target
+   if (Pkg->TargetVer == 0)
+   {
+      /* Not source versions cannot be a candidate version unless they
+         are already installed */
+      for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
+      {
+	 if (Pkg.CurrentVer() == I)
+	    return I;
+	 for (VerFileIterator J = I.FileList(); J.end() == false; J++)
+	    if ((J.File()->Flags & Flag::NotSource) == 0)
+		return I;
+      }
+	 
+      return VerIterator(*this,0);
+   }
+   else
+      return Pkg.TargetVer(); 
+}
+									/*}}}*/
+// DepCache::IsImportantDep - True if the dependency is important	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgDepCache::IsImportantDep(DepIterator Dep)
+{
+   return Dep.IsCritical();
+}
+									/*}}}*/
+
+// DepCache::CheckDep - Checks a single dependency			/*{{{*/
+// ---------------------------------------------------------------------
+/* This first checks the dependency against the main target package and
+   then walks along the package provides list and checks if each provides 
+   will be installed then checks the provides against the dep. Res will be 
+   set to the package which was used to satisfy the dep. */
+bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
+{
+   Res = Dep.TargetPkg();
+
+   /* Check simple depends. A depends -should- never self match but 
+      we allow it anyhow because dpkg does. Technically it is a packaging
+      bug. Conflicts may never self match */
+   if (Dep.TargetPkg() != Dep.ParentPkg() || Dep->Type != Dep::Conflicts)
+   {
+      PkgIterator Pkg = Dep.TargetPkg();
+      // Check the base package
+      if (Type == NowVersion && Pkg->CurrentVer != 0)
+	 if (pkgCheckDep(Dep.TargetVer(),
+			 Pkg.CurrentVer().VerStr(),Dep->CompareOp) == true)
+	    return true;
+      
+      if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
+	 if (pkgCheckDep(Dep.TargetVer(),
+			 PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
+			 Dep->CompareOp) == true)
+	    return true;
+      
+      if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
+	 if (pkgCheckDep(Dep.TargetVer(),
+			 PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
+			 Dep->CompareOp) == true)
+	    return true;
+   }
+   
+   // Check the providing packages
+   PrvIterator P = Dep.TargetPkg().ProvidesList();
+   PkgIterator Pkg = Dep.ParentPkg();
+   for (; P.end() != true; P++)
+   {
+      /* Provides may never be applied against the same package if it is
+         a conflicts. See the comment above. */
+      if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
+	 continue;
+      
+      // Check if the provides is a hit
+      if (Type == NowVersion)
+      {
+	 if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
+	    continue;
+      }
+      
+      if (Type == InstallVersion)
+      {
+	 StateCache &State = PkgState[P.OwnerPkg()->ID];
+	 if (State.InstallVer != (Version *)P.OwnerVer())
+	    continue;
+      }
+
+      if (Type == CandidateVersion)
+      {
+	 StateCache &State = PkgState[P.OwnerPkg()->ID];
+	 if (State.CandidateVer != (Version *)P.OwnerVer())
+	    continue;
+      }
+      
+      // Compare the versions.
+      if (pkgCheckDep(Dep.TargetVer(),P.ProvideVersion(),Dep->CompareOp) == true)
+      {
+	 Res = P.OwnerPkg();
+	 return true;
+      }
+   }
+   
+   return false;
+}
+									/*}}}*/
+// DepCache::AddSizes - Add the packages sizes to the counters		/*{{{*/
+// ---------------------------------------------------------------------
+/* Call with Mult = -1 to preform the inverse opration */
+void pkgDepCache::AddSizes(const PkgIterator &Pkg,long Mult)
+{
+   StateCache &P = PkgState[Pkg->ID];
+   
+   // Compute the size data
+   if (P.NewInstall() == true)
+   {
+      iUsrSize += Mult*P.InstVerIter(*this)->InstalledSize;
+      iDownloadSize += Mult*P.InstVerIter(*this)->Size;
+   }
+   
+   // Upgrading
+   if (Pkg->CurrentVer != 0 && P.InstallVer != (Version *)Pkg.CurrentVer() &&
+       P.InstallVer != 0)
+   {
+      iUsrSize += Mult*(P.InstVerIter(*this)->InstalledSize - 
+			Pkg.CurrentVer()->InstalledSize);
+      iDownloadSize += Mult*P.InstVerIter(*this)->Size;
+   }
+   
+   // Removing
+   if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
+      iUsrSize -= Mult*Pkg.CurrentVer()->InstalledSize;
+}
+									/*}}}*/
+// DepCache::AddStates - Add the package to the state counter		/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine is tricky to use, you must make sure that it is never 
+   called twice for the same package. This means the Remove/Add section
+   should be as short as possible and not encompass any code that will 
+   calld Remove/Add itself. Remember, dependencies can be circular so
+   while processing a dep for Pkg it is possible that Add/Remove
+   will be called on Pkg */
+void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
+{
+   StateCache &State = PkgState[Pkg->ID];
+   
+   // The Package is broken
+   if ((State.DepState & DepInstMin) != DepInstMin)
+      iBrokenCount += Add;
+   
+   // Bad state
+   if (Pkg.State() != PkgIterator::NeedsNothing)
+      iBadCount += Add;
+   
+   // Not installed
+   if (Pkg->CurrentVer == 0)
+   {
+      if (State.Mode == ModeInstall)
+	 iInstCount += Add;
+      return;
+   }
+   
+   // Installed, no upgrade
+   if (State.Upgradable() == false)
+   {
+      if (State.Mode == ModeDelete)
+	 iDelCount += Add;
+      return;
+   }
+   
+   // Alll 3 are possible
+   if (State.Mode == ModeDelete)
+      iDelCount += Add;   
+   if (State.Mode == ModeKeep)
+      iKeepCount += Add;
+   if (State.Mode == ModeInstall)
+      iInstCount += Add;
+}
+									/*}}}*/
+// DepCache::BuildGroupOrs - Generate the Or group dep data		/*{{{*/
+// ---------------------------------------------------------------------
+/* The or group results are stored in the last item of the or group. This
+   allows easy detection of the state of a whole or'd group. */
+void pkgDepCache::BuildGroupOrs(VerIterator const &V)
+{
+   unsigned char Group = 0;
+   
+   for (DepIterator D = V.DependsList(); D.end() != true; D++)
+   {
+      // Build the dependency state.
+      unsigned char &State = DepState[D->ID];
+
+      /* Invert for Conflicts. We have to do this twice to get the
+         right sense for a conflicts group */
+      if (D->Type == Dep::Conflicts)
+	 State = ~State;
+      
+      // Add to the group if we are within an or..
+      Group |= State;
+      State |= Group << 3;
+      if ((D->CompareOp & Dep::Or) != Dep::Or)
+	 Group = 0;
+      
+      // Invert for Conflicts
+      if (D->Type == Dep::Conflicts)
+	 State = ~State;
+   }	 
+}
+									/*}}}*/
+// DepCache::VersionState - Perform a pass over a dependency list	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is used to run over a dependency list and determine the dep
+   state of the list, filtering it through both a Min check and a Policy
+   check. The return result will have SetMin/SetPolicy low if a check
+   fails. It uses the DepState cache for it's computations. */
+unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
+				       unsigned char SetMin,
+				       unsigned char SetPolicy)
+{
+   unsigned char Dep = 0xFF;
+   
+   while (D.end() != true)
+   {
+      // Compute a single dependency element (glob or)
+      DepIterator Start = D;
+      unsigned char State = 0;
+      for (bool LastOR = true; D.end() == false && LastOR == true; D++)
+      {
+	 State |= DepState[D->ID];
+	 LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
+      }
+	
+      // Minimum deps that must be satisfied to have a working package
+      if (Start.IsCritical() == true)
+	 if ((State & Check) != Check)
+	    Dep &= ~SetMin;
+      
+      // Policy deps that must be satisfied to install the package
+      if (IsImportantDep(Start) == true && 
+	  (State & Check) != Check)
+	 Dep &= ~SetPolicy;
+   }
+
+   return Dep;
+}
+									/*}}}*/
+// DepCache::DependencyState - Compute the 3 results for a dep		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is the main dependency computation bit. It computes the 3 main
+   results for a dependencys, Now, Install and Candidate. Callers must
+   invert the result if dealing with conflicts. */
+unsigned char pkgDepCache::DependencyState(DepIterator &D)
+{
+   unsigned char State = 0;
+   
+   if (CheckDep(D,NowVersion) == true)
+      State |= DepNow;
+   if (CheckDep(D,InstallVersion) == true)
+      State |= DepInstall;
+   if (CheckDep(D,CandidateVersion) == true)
+      State |= DepCVer;
+   
+   return State;
+}
+									/*}}}*/
+// DepCache::UpdateVerState - Compute the Dep member of the state	/*{{{*/
+// ---------------------------------------------------------------------
+/* This determines the combined dependency representation of a package
+   for its two states now and install. This is done by using the pre-generated
+   dependency information. */
+void pkgDepCache::UpdateVerState(PkgIterator Pkg)
+{   
+   // Empty deps are always true
+   StateCache &State = PkgState[Pkg->ID];
+   State.DepState = 0xFF;
+   
+   // Check the Current state
+   if (Pkg->CurrentVer != 0)
+   {
+      DepIterator D = Pkg.CurrentVer().DependsList();
+      State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
+   }
+   
+   /* Check the candidate state. We do not compare against the whole as
+      a candidate state but check the candidate version against the 
+      install states */
+   if (State.CandidateVer != 0)
+   {
+      DepIterator D = State.CandidateVerIter(*this).DependsList();
+      State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
+   }
+   
+   // Check target state which can only be current or installed
+   if (State.InstallVer != 0)
+   {
+      DepIterator D = State.InstVerIter(*this).DependsList();
+      State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
+   }
+}
+									/*}}}*/
+// DepCache::Update - Figure out all the state information		/*{{{*/
+// ---------------------------------------------------------------------
+/* This will figure out the state of all the packages and all the 
+   dependencies based on the current policy. */
+void pkgDepCache::Update()
+{   
+   iUsrSize = 0;
+   iDownloadSize = 0;
+   iDelCount = 0;
+   iInstCount = 0;
+   iKeepCount = 0;
+   iBrokenCount = 0;
+   iBadCount = 0;
+   
+   // Perform the depends pass
+   for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+   {
+      for (VerIterator V = I.VersionList(); V.end() != true; V++)
+      {
+	 unsigned char Group = 0;
+	 
+	 for (DepIterator D = V.DependsList(); D.end() != true; D++)
+	 {
+	    // Build the dependency state.
+	    unsigned char &State = DepState[D->ID];
+	    State = DependencyState(D);;
+
+	    // Add to the group if we are within an or..
+	    Group |= State;
+	    State |= Group << 3;
+	    if ((D->CompareOp & Dep::Or) != Dep::Or)
+	       Group = 0;
+
+	    // Invert for Conflicts
+	    if (D->Type == Dep::Conflicts)
+	       State = ~State;
+	 }	 
+      }
+
+      // Compute the pacakge dependency state and size additions
+      AddSizes(I);
+      UpdateVerState(I);
+      AddStates(I);
+   }
+}
+									/*}}}*/
+// DepCache::Update - Update the deps list of a package	   		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is a helper for update that only does the dep portion of the scan. 
+   It is mainly ment to scan reverse dependencies. */
+void pkgDepCache::Update(DepIterator D)
+{
+   // Update the reverse deps
+   for (;D.end() != true; D++)
+   {      
+      unsigned char &State = DepState[D->ID];
+      State = DependencyState(D);
+    
+      // Invert for Conflicts
+      if (D->Type == Dep::Conflicts)
+	 State = ~State;
+      
+      RemoveStates(D.ParentPkg());
+      BuildGroupOrs(D.ParentVer());
+      UpdateVerState(D.ParentPkg());
+      AddStates(D.ParentPkg());
+   }
+}
+									/*}}}*/
+// DepCache::Update - Update the related deps of a package		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is called whenever the state of a package changes. It updates
+   all cached dependencies related to this package. */
+void pkgDepCache::Update(PkgIterator const &Pkg)
+{
+   // Recompute the dep of the package
+   RemoveStates(Pkg);
+   UpdateVerState(Pkg);
+   AddStates(Pkg);
+   
+   // Update the reverse deps
+   Update(Pkg.RevDependsList());
+
+   // Update the provides map for the current ver
+   if (Pkg->CurrentVer != 0)
+      for (PrvIterator P = Pkg.CurrentVer().ProvidesList(); 
+	   P.end() != true; P++)
+	 Update(P.ParentPkg().RevDependsList());
+
+   // Update the provides map for the candidate ver
+   for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
+	P.end() != true; P++)
+      Update(P.ParentPkg().RevDependsList());
+}
+
+									/*}}}*/
+
+// DepCache::MarkKeep - Put the package in the keep state		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
+{
+   // Simplifies other routines.
+   if (Pkg.end() == true)
+      return;
+   
+   /* We changed the soft state all the time so the UI is a bit nicer
+      to use */
+   StateCache &P = PkgState[Pkg->ID];
+   if (Soft == true)
+      P.iFlags |= AutoKept;
+   else
+      P.iFlags &= ~AutoKept;
+   
+   // Check that it is not already kept
+   if (P.Mode == ModeKeep)
+      return;
+
+   // We dont even try to keep virtual packages..
+   if (Pkg->VersionList == 0)
+      return;
+   
+   P.Flags &= ~Flag::Auto;
+   RemoveSizes(Pkg);
+   RemoveStates(Pkg);
+
+   P.Mode = ModeKeep;
+   if (Pkg->CurrentVer == 0)
+      P.InstallVer = 0;
+   else
+      P.InstallVer = Pkg.CurrentVer();
+
+   AddStates(Pkg);
+
+   Update(Pkg);
+
+   AddSizes(Pkg);
+}
+									/*}}}*/
+// DepCache::MarkDelete - Put the package in the delete state		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDepCache::MarkDelete(PkgIterator const &Pkg)
+{
+   // Simplifies other routines.
+   if (Pkg.end() == true)
+      return;
+
+   // Check that it is not already marked for delete
+   StateCache &P = PkgState[Pkg->ID];
+   P.iFlags &= ~AutoKept;
+   if (P.Mode == ModeDelete || P.InstallVer == 0)
+      return;
+
+   // We dont even try to delete virtual packages..
+   if (Pkg->VersionList == 0)
+      return;
+
+   RemoveSizes(Pkg);
+   RemoveStates(Pkg);
+   
+   P.Mode = ModeDelete;
+   P.InstallVer = 0;
+   P.Flags &= Flag::Auto;
+
+   AddStates(Pkg);   
+   Update(Pkg);
+   AddSizes(Pkg);
+}
+									/*}}}*/
+// DepCache::MarkInstall - Put the package in the install state		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst)
+{   
+   // Simplifies other routines.
+   if (Pkg.end() == true)
+      return;
+   
+   /* Check that it is not already marked for install and that it can be 
+      installed */
+   StateCache &P = PkgState[Pkg->ID];
+   P.iFlags &= ~AutoKept;
+   if (P.InstBroken() == false && (P.Mode == ModeInstall ||
+	P.CandidateVer == (Version *)Pkg.CurrentVer()))
+   {
+      if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
+	 MarkKeep(Pkg);
+      return;
+   }
+   
+   // We dont even try to install virtual packages..
+   if (Pkg->VersionList == 0)
+      return;
+   
+   /* Target the candidate version and remove the autoflag. We reset the
+      autoflag below if this was called recursively. Otherwise the user
+      should have the ability to de-auto a package by changing its state */
+   RemoveSizes(Pkg);
+   RemoveStates(Pkg);
+   
+   P.Mode = ModeInstall;
+   P.InstallVer = P.CandidateVer;
+   P.Flags &= ~Flag::Auto;
+   if (P.CandidateVer == (Version *)Pkg.CurrentVer())
+      P.Mode = ModeKeep;
+       
+   AddStates(Pkg);
+   Update(Pkg);
+   AddSizes(Pkg);
+   
+   if (AutoInst == false)
+      return;
+
+   DepIterator Dep = P.InstVerIter(*this).DependsList();
+   for (; Dep.end() != true;)
+   {
+      // Grok or groups
+      DepIterator Start = Dep;
+      bool Result = true;
+      for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++)
+      {
+	 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
+
+	 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
+	    Result = false;
+      }
+      
+      // Dep is satisfied okay.
+      if (Result == false)
+	 continue;
+
+      /* Check if this dep should be consider for install. If it is a user
+         defined important dep and we are installed a new package then 
+	 it will be installed. Otherwise we only worry about critical deps */
+      if (IsImportantDep(Start) == false)
+	 continue;
+      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
+	 continue;
+
+      // Now we have to take action...
+      PkgIterator P = Start.SmartTargetPkg();
+      if ((DepState[Start->ID] & DepCVer) == DepCVer)
+      {
+	 MarkInstall(P,true);
+	 
+	 // Set the autoflag, after MarkInstall because MarkInstall unsets it
+	 if (P->CurrentVer == 0)
+	    PkgState[P->ID].Flags |= Flag::Auto;
+
+	 continue;
+      }
+      
+      // For conflicts we just de-install the package and mark as auto
+      if (Start->Type == Dep::Conflicts)
+      {
+	 Version **List = Start.AllTargets();
+	 for (Version **I = List; *I != 0; I++)
+	 {
+	    VerIterator Ver(*this,*I);
+	    PkgIterator Pkg = Ver.ParentPkg();
+      
+	    MarkDelete(Pkg);
+	    PkgState[Pkg->ID].Flags |= Flag::Auto;
+	 }
+	 delete [] List;
+	 continue;
+      }      
+   }
+}
+									/*}}}*/
+
+#if 0
+// DepCache::ResolveConflicts - Figure the auto upgrades		/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine attempts to resolve conflicts generated by automatic 
+   upgrading. It is known as 'Stage 1' but that name isn't as proper anymore.
+   
+   It's most important function is during the initial load of APT. The 
+   loading code will mark every package for upgrade to it's candidate version
+   and then call this routine. This routine will then 'soft keep' every
+   package that causes conflict, is conflicted, or so on. It is a bit
+   agressive in that it may unselect more packages in some odd cases
+   than are strictly necessary but in the case where no packages were
+   conflicting before it will always produce a system with no packages
+   conflicting after.
+ 
+   This routine is also used during state changes that require autoupgrade
+   scanning. That is, if a new package is marked for install then all packages
+   that have been soft kept are reconsidered for upgrade. 
+   
+   It is called with state information about what can be un-upgraded and
+   what the pre-upgrade install state was. It is expected that the caller
+   has already marked the desired packages to the install state. Bit 0 is
+   the original install state and Bit 1 is controls whether the package
+   should be touched.
+*/
+void pkgDepCache::ResolveConflicts(unsigned char *Touched)
+{
+   bool Again = false;
+   do
+   {
+      Again = false;
+      for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+      {
+	 // The package will install OK
+	 if ((PkgState[I->ID].DepState & DepInstMin) == DepInstMin)
+	    continue;
+	 
+	 /* The package was broken before and this upgrade will not
+	    make things better. We simply mark the package for keep
+	    and assume an upgrade attempt will be hopeless. This might
+	    not be ideal. */
+	 if ((Touched[I->ID] & (1 << 0)) != (1 << 0))
+	 {
+	    // The package isnt to be touched
+	    if ((Touched[I->ID] & (1 << 1)) == (1 << 1))
+	       MarkKeep(I,true);
+	    
+	    continue;
+	 }	 
+	 
+	 // Check to see if not upgrading it will solve the problem
+	 if (I->CurrentVer != 0)
+	 {	    
+	    // The package isnt to be touched
+	    if ((Touched[I->ID] & (1 << 1)) == (1 << 1))
+	    {
+	       if (PkgState[I->ID].Mode != ModeKeep)
+		  Again = true;
+	       
+	       MarkKeep(I,true);
+	    }
+	    
+	    /* Check if the package is sill broken. If so then we cant leave 
+	       it as is and get a working system. Lets try marking some 
+	       depends for 'keep'. This is brutal, it keeps everything in 
+	       sight to fix the problem. */
+	    DepIterator D = I.CurrentVer().DependsList();
+	    for (;(PkgState[I->ID].DepState & DepInstMin) != DepInstMin && 
+		   D.end() != true; D++)
+	    {
+	       // We only worry about critical deps.
+	       if (D.IsCritical() != true)
+		  continue;
+	       
+	       unsigned char State = DepState[D->ID];
+	       
+	       // This dep never was set before so we dont need to set it now
+	       if ((State & DepNow) != DepNow)
+		  continue;
+
+	       // The dep is okay now no worries.
+	       if ((State & DepInstall) == DepInstall)
+		  continue;
+
+	       // Locate a target to keep
+	       PkgIterator P(*this);
+	       if (CheckDep(D,NowVersion,P) == true)
+	       {
+		  // We cant touch this package
+		  if ((Touched[P->ID] & (1 << 1)) == (1 << 1))
+		     MarkKeep(P,true);
+	       }
+	    }
+	 }
+      }
+   }
+   while (Again == true);
+}
+									/*}}}*/
+// DepCache::PromoteAutoKeep - Gentler version of the above		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is used when installing packages, all it does is attempt to promote
+   everything that has been auto-kept. It simply promotes everything
+   irregardless of it having a chance to work and then runs ResolveConflicts
+   on the result. This allows circular depends loops to work but isn't
+   terribly fast. */
+void pkgDepCache::PromoteAutoKeep()
+{
+   /* Initialize the touchd array. Bit 0 is the old install state bit 1
+      is the touch value */
+   unsigned char *Touch = new unsigned char[Head().PackageCount];
+   for (unsigned int I = 0; I != Head().PackageCount; I++)
+   {
+      if ((PkgState[I].DepState & DepInstMin) == DepInstMin)
+	 Touch[I] = 1 << 0;
+      else
+	 Touch[I] = 0;
+   }
+
+   // This allows circular depends to work
+   for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+   {
+      /* It wasnt installed before or it is not autokept or it is not
+       upgradeable */
+      StateCache &P = PkgState[I->ID];
+      if (I->CurrentVer == 0 || P.Mode != ModeKeep || I->VersionList == 0 ||
+	  P.CandidateVer == (Version *)I.CurrentVer() || 
+	  (P.iFlags & AutoKept) != AutoKept)
+	 continue;
+
+      P.Mode = ModeInstall;
+      P.InstallVer = P.CandidateVer;
+      if (P.CandidateVer == (Version *)I.CurrentVer())
+	 P.Mode = ModeKeep;
+      
+      // Okay autoupgrade it.
+      Touch[I->ID] |= 1 << 1;
+   }
+   
+   Update();   
+   ResolveConflicts(Touch);
+   
+   delete [] Touch;
+}
+									/*}}}*/
+// DepCache::AllUpgrade - Try to upgrade everything			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDepCache::AllUpgrade()
+{
+   // Set everything to an upgrade mode 
+   for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+   {
+      StateCache &State = PkgState[I->ID];
+      
+      /* We dont upgrade packages marked for deletion or that are
+         not installed or that don't have an upgrade */
+      if (State.Mode == ModeDelete || I->CurrentVer == 0 ||
+	  (Version *)I.CurrentVer() == State.CandidateVer)
+	 continue;
+	
+      // Set the state to upgrade
+      State.iFlags = 0;
+      State.Mode = ModeInstall;
+      State.InstallVer = State.CandidateVer;
+      if (State.CandidateVer == (Version *)I.CurrentVer())
+	 State.Mode = ModeKeep;
+      
+      // Do not upgrade things that have the hold flag set.
+      if (I->SelectedState == State::Hold)
+      {
+	 State.InstallVer = I.CurrentVer();
+	 State.Mode = ModeKeep;
+      }
+      State.Update(I,*this);
+   }   
+   
+   Update();
+
+   /* Initialize the touchd array. Bit 0 is the old install state bit 1
+      is the touch value */
+   unsigned char *Touch = new unsigned char[Head().PackageCount];
+   for (unsigned int I = 0; I != Head().PackageCount; I++)
+   {
+      if ((PkgState[I].DepState & DepNowMin) == DepNowMin)
+	 Touch[I] = (1 << 0) | (1 << 1);
+      else
+	 Touch[I] = 1 << 1;
+   }
+
+   // Now downgrade everything that is broken
+   ResolveConflicts(Touch);
+   delete [] Touch;
+}
+									/*}}}*/
+#endif
+
+// StateCache::Update - Compute the various static display things	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is called whenever the Candidate version changes. */
+void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
+{
+   // Some info
+   VerIterator Ver = CandidateVerIter(Cache);
+   
+   // Use a null string or the version string
+   if (Ver.end() == true)
+      CandVersion = "";
+   else
+      CandVersion = Ver.VerStr();
+   
+   // Find the current version
+   CurVersion = "";
+   if (Pkg->CurrentVer != 0)
+      CurVersion = Pkg.CurrentVer().VerStr();
+   
+   // Strip off the epochs for display
+   CurVersion = StripEpoch(CurVersion);
+   CandVersion = StripEpoch(CandVersion);
+   
+   // Figure out if its up or down or equal
+   Status = Ver.CompareVer(Pkg.CurrentVer());
+   if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
+     Status = 2;      
+}
+									/*}}}*/
+// StateCache::StripEpoch - Remove the epoch specifier from the version	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
+{
+   if (Ver == 0)
+      return 0;
+
+   // Strip any epoch
+   for (const char *I = Ver; *I != 0; I++)
+      if (*I == ':')
+	 return I + 1;
+   return Ver;
+}
+									/*}}}*/
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
new file mode 100644
index 000000000..222e34425
--- /dev/null
+++ b/apt-pkg/depcache.h
@@ -0,0 +1,189 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: depcache.h,v 1.1 1998/07/07 04:17:01 jgg Exp $
+/* ######################################################################
+
+   DepCache - Dependency Extension data for the cache
+   
+   This class stores the cache data and a set of extension structures for
+   monitoring the current state of all the packages. It also generates and
+   caches the 'install' state of many things. This refers to the state of the
+   package after an install has been run.
+
+   The StateCache::State field can be -1,0,1,2 which is <,=,>,no current.
+   StateCache::Mode is which of the 3 fields is active.
+   
+   This structure is important to support the readonly status of the cache 
+   file. When the data is saved the cache will be refereshed from our 
+   internal rep and written to disk. Then the actual persistant data 
+   files will be put on the disk.
+
+   Each dependency is compared against 3 target versions to produce to
+   3 dependency results.
+     Now - Compared using the Currently install version
+     Install - Compared using the install version (final state)
+     CVer - (Candidate Verion) Compared using the Candidate Version
+   The candidate and now results are used to decide wheather a package
+   should be automatically installed or if it should be left alone.
+   
+   Remember, the Candidate Version is selected based on the distribution
+   settings for the Package. The Install Version is selected based on the
+   state (Delete, Keep, Install) field and can be either the Current Version
+   or the Candidate version.
+   
+   The Candidate version is what is shown the 'Install Version' field.
+   
+   ##################################################################### */
+									/*}}}*/
+// Header section: pkglib
+#ifndef PKGLIB_DEPCACHE_H
+#define PKGLIB_DEPCACHE_H
+
+#ifdef __GNUG__
+#pragma interface "pkglib/depcache.h"
+#endif
+
+#include <pkglib/pkgcache.h>
+
+class pkgDepCache : public pkgCache
+{
+   public:
+   
+   // These flags are used in DepState
+   enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
+                  DepGNow = (1 << 3),DepGInstall = (1 << 4),DepGCVer = (1 << 5)};
+
+   // These flags are used in StateCache::DepState
+   enum DepStateFlags {DepNowPolicy = (1 << 0), DepNowMin = (1 << 1),
+                       DepInstPolicy = (1 << 2), DepInstMin = (1 << 3),
+                       DepCandPolicy = (1 << 4), DepCandMin = (1 << 5)};
+   
+   // These flags are used in StateCache::iFlags
+   enum InternalFlags {AutoKept = (1 << 0)};
+      
+   enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
+   enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
+   struct StateCache
+   {
+      // Epoch stripped text versions of the two version fields
+      const char *CandVersion;
+      const char *CurVersion;
+
+      // Pointer to the candidate install version. 
+      Version *CandidateVer;
+
+      // Pointer to the install version.
+      Version *InstallVer;
+
+      // Various tree indicators
+      signed char Status;              // -1,0,1,2
+      unsigned char Mode;              // ModeList
+      unsigned char DepState;          // DepState Flags
+
+      // Copy of Package::Flags
+      unsigned short Flags;
+      unsigned short iFlags;           // Internal flags
+
+      // Update of candidate version
+      const char *StripEpoch(const char *Ver);
+      void Update(PkgIterator Pkg,pkgCache &Cache);
+      
+      // Various test members for the current status of the package
+      inline bool NewInstall() const {return Status == 2 && Mode == ModeInstall;};
+      inline bool Delete() const {return Mode == ModeDelete;};
+      inline bool Keep() const {return Mode == ModeKeep;};
+      inline bool Upgrade() const {return Status > 0 && Mode == ModeInstall;};
+      inline bool Upgradable() const {return Status == 1;};
+      inline bool Downgrade() const {return Status < 0;};
+      inline bool Held() const {return Status != 0 && Keep();};
+      inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
+      inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
+      inline bool Install() const {return Mode == ModeInstall;};
+      inline VerIterator InstVerIter(pkgCache &Cache)
+                {return VerIterator(Cache,InstallVer);};
+      inline VerIterator CandidateVerIter(pkgCache &Cache)
+                {return VerIterator(Cache,CandidateVer);};
+   };
+   
+   // Helper functions
+   void BuildGroupOrs(VerIterator const &V);
+   void UpdateVerState(PkgIterator Pkg);
+
+   bool Init();
+
+   protected:
+
+   // State information
+   StateCache *PkgState;
+   unsigned char *DepState;
+   
+   long iUsrSize;
+   long iDownloadSize;
+   long iInstCount;
+   long iDelCount;
+   long iKeepCount;
+   long iBrokenCount;
+   long iBadCount;
+      
+   // Check for a matching provides
+   bool CheckDep(DepIterator Dep,int Type,PkgIterator &Res);
+   inline bool CheckDep(DepIterator Dep,int Type)
+   {
+      PkgIterator Res(*this);
+      return CheckDep(Dep,Type,Res);
+   } 
+   
+   // Computes state information for deps and versions (w/o storing)
+   unsigned char DependencyState(DepIterator &D);
+   unsigned char VersionState(DepIterator D,unsigned char Check,
+			      unsigned char SetMin,
+			      unsigned char SetPolicy);
+
+   // Recalculates various portions of the cache, call after changing something
+   void Update(DepIterator Dep);           // Mostly internal
+   void Update(PkgIterator const &P);
+   
+   // Count manipulators
+   void AddSizes(const PkgIterator &Pkg,long Mult = 1);
+   inline void RemoveSizes(const PkgIterator &Pkg) {AddSizes(Pkg,-1);};
+   void AddStates(const PkgIterator &Pkg,int Add = 1);
+   inline void RemoveStates(const PkgIterator &Pkg) {AddStates(Pkg,-1);};
+
+   public:
+
+   // Policy implementation
+   virtual VerIterator GetCandidateVer(PkgIterator Pkg);
+   virtual bool IsImportantDep(DepIterator Dep);
+         
+   // Accessors
+   inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
+   inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
+
+   // Manipulators
+   void MarkKeep(PkgIterator const &Pkg,bool Soft = false);
+   void MarkDelete(PkgIterator const &Pkg);
+   void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true);
+   
+   // This is for debuging
+   void Update();
+
+   // Dep Processing for AutoKeep
+   void ResolveConflicts(unsigned char *Touched);
+   
+   // Hook to keep the extra data in sync
+   virtual bool ReMap();
+   
+   // Size queries
+   inline long UsrSize() {return iUsrSize;};
+   inline long DebSize() {return iDownloadSize;};
+   inline long DelCount() {return iDelCount;};
+   inline long KeepCount() {return iKeepCount;};
+   inline long InstCount() {return iInstCount;};
+   inline long BrokenCount() {return iBrokenCount;};
+   inline long BadCount() {return iBadCount;};
+   
+   pkgDepCache(MMap &Map);
+   virtual ~pkgDepCache();
+};
+
+#endif
diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc
new file mode 100644
index 000000000..f79a063bd
--- /dev/null
+++ b/apt-pkg/orderlist.cc
@@ -0,0 +1,829 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: orderlist.cc,v 1.1 1998/07/07 04:17:01 jgg Exp $
+/* ######################################################################
+
+   Order List - Represents and Manipulates an ordered list of packages.
+   
+   A list of packages can be ordered by a number of conflicting criteria
+   each given a specific priority. Each package also has a set of flags
+   indicating some usefull things about it that are derived in the 
+   course of sorting. The pkgPackageManager class uses this class for
+   all of it's installation ordering needs.
+
+   This is a modified version of Manoj's Routine B. It consists of four
+   independent ordering algorithms that can be applied at for different
+   points in the ordering. By appling progressivly fewer ordering
+   operations it is possible to give each consideration it's own
+   priority and create an order that satisfies the lowest applicable
+   consideration.
+   
+   The rules for unpacking ordering are:
+    1) Unpacking ignores Depends: on all packages
+    2) Unpacking requires Conflicts: on -ALL- packages to be satisfied
+    3) Unpacking requires PreDepends: on this package only to be satisfied
+    4) Removing requires that no packages depend on the package to be
+       removed.
+   
+   And the rule for configuration ordering is:
+    1) Configuring requires that the Depends: of the package be satisfied
+       Conflicts+PreDepends are ignored because unpacking says they are 
+       already correct [exageration, it does check but we need not be 
+       concerned]
+
+   And some features that are valuable for unpacking ordering.
+     f1) Unpacking a new package should advoid breaking dependencies of
+         configured packages
+     f2) Removal should not require a force, corrolory of f1
+     f3) Unpacking should order by depends rather than fall back to random
+         ordering.  
+   
+   Each of the features can be enabled in the sorting routine at an 
+   arbitary priority to give quite abit of control over the final unpacking
+   order.
+
+   The rules listed above my never be violated and are called Critical.
+   When a critical rule is violated then a loop condition is recorded
+   and will have to be delt with in the caller.
+   
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/orderlist.h"
+#endif 
+#include <pkglib/orderlist.h>
+#include <pkglib/depcache.h>
+#include <pkglib/error.h>
+#include <pkglib/version.h>
+									/*}}}*/
+
+pkgOrderList *pkgOrderList::Me = 0;
+
+// OrderList::pkgOrderList - Constructor				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgOrderList::pkgOrderList(pkgDepCache &Cache) : Cache(Cache)
+{
+   Primary = 0;
+   Secondary = 0;
+   RevDepends = 0;
+   Remove = 0;
+   LoopCount = -1;
+
+   /* Construct the arrays, egcs 1.0.1 bug requires the package count
+      hack */
+   unsigned long Size = Cache.HeaderP->PackageCount;
+   Flags = new unsigned char[Size];
+   End = List = new Package *[Size];
+   memset(Flags,0,sizeof(*Flags)*Size);
+}
+									/*}}}*/
+// OrderList::~pkgOrderList - Destructor				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgOrderList::~pkgOrderList()
+{
+   delete [] List;
+   delete [] Flags;
+}
+									/*}}}*/
+
+// OrderList::DoRun - Does an order run					/*{{{*/
+// ---------------------------------------------------------------------
+/* The caller is expeted to have setup the desired probe state */
+bool pkgOrderList::DoRun()
+{
+   // Temp list
+   unsigned long Size = Cache.HeaderP->PackageCount;
+   Package **NList = new Package *[Size];
+
+   Depth = 0;
+   WipeFlags(Added | AddPending | Loop | InList);
+
+   for (iterator I = List; I != End; I++)
+      Flag(*I,InList);
+   
+   // Rebuild the main list into the temp list.
+   iterator OldEnd = End;
+   End = NList;
+   for (iterator I = List; I != OldEnd; I++)
+      if (VisitNode(PkgIterator(Cache,*I)) == false)
+      {
+	 End = OldEnd;
+	 delete [] NList;
+	 return false;
+      }
+   
+   // Swap the main list to the new list
+   delete [] List;
+   List = NList;
+   return true;
+}
+									/*}}}*/
+// OrderList::OrderCritical - Perform critical unpacking ordering	/*{{{*/
+// ---------------------------------------------------------------------
+/* This performs predepends and immediate configuration ordering only. 
+   This is termed critical unpacking ordering. Any loops that form are
+   fatal and indicate that the packages cannot be installed. */
+bool pkgOrderList::OrderCritical()
+{
+   Primary = &DepUnPackPre;
+   Secondary = 0;
+   RevDepends = 0;
+   Remove = 0;
+   LoopCount = 0;
+   
+   // Sort
+   Me = this;
+   qsort(List,End - List,sizeof(*List),&OrderCompareB);   
+   
+   if (DoRun() == false)
+      return false;
+   
+   if (LoopCount != 0)
+      return _error->Error("Fatal, predepends looping detected");
+   return true;
+}
+									/*}}}*/
+// OrderList::OrderUnpack - Perform complete unpacking ordering		/*{{{*/
+// ---------------------------------------------------------------------
+/* This performs complete unpacking ordering and creates an order that is
+   suitable for unpacking */
+bool pkgOrderList::OrderUnpack()
+{
+   Primary = &DepUnPackCrit;
+   Secondary = &DepConfigure;
+   RevDepends = &DepUnPackDep;
+   Remove = &DepRemove;
+   LoopCount = -1;
+
+   // Sort
+   Me = this;
+   qsort(List,End - List,sizeof(*List),&OrderCompareA);
+   
+   if (DoRun() == false)
+      return false;
+   
+   Secondary = 0;
+   if (DoRun() == false)
+      return false;
+
+   LoopCount = 0;
+   RevDepends = 0;
+   Remove = 0;             // Otherwise the libreadline remove problem occures
+   if (DoRun() == false)
+      return false;
+
+   LoopCount = 0;
+   Primary = &DepUnPackPre;
+   if (DoRun() == false)
+      return false;
+
+/*   cout << "----------END" << endl;
+
+   for (iterator I = List; I != End; I++)
+   {
+      PkgIterator P(Cache,*I);
+      cout << P.Name() << endl;
+   }*/
+
+   return true;
+}
+									/*}}}*/
+// OrderList::OrderConfigure - Perform configuration ordering		/*{{{*/
+// ---------------------------------------------------------------------
+/* This orders by depends only and produces an order which is suitable
+   for configuration */
+bool pkgOrderList::OrderConfigure()
+{
+   Primary = &DepConfigure;
+   Secondary = 0;
+   RevDepends = 0;
+   Remove = 0;
+   LoopCount = -1;
+   return DoRun();
+}
+									/*}}}*/
+
+// OrderList::Score - Score the package for sorting			/*{{{*/
+// ---------------------------------------------------------------------
+/* Higher scores order earlier */
+int pkgOrderList::Score(PkgIterator Pkg)
+{
+   // Removal is always done first
+   if (Cache[Pkg].Delete() == true)
+      return 200;
+
+   int Score = 0;
+   if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+      Score += 100;
+
+   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); 
+	D.end() == false; D++)
+      if (D->Type == pkgCache::Dep::PreDepends)
+      {
+	 Score += 50;
+	 break;
+      }
+      
+   // Important Required Standard Optional Extra
+   signed short PrioMap[] = {0,5,4,3,1,0};
+   if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
+      Score += PrioMap[Cache[Pkg].InstVerIter(Cache)->Priority];
+   return Score;
+}
+									/*}}}*/
+// OrderList::FileCmp - Compare by package file				/*{{{*/
+// ---------------------------------------------------------------------
+/* This compares by the package file that the install version is in. */
+int pkgOrderList::FileCmp(PkgIterator A,PkgIterator B)
+{
+   if (Cache[A].Delete() == true && Cache[B].Delete() == true)
+      return 0;
+   if (Cache[A].Delete() == true)
+      return -1;
+   if (Cache[B].Delete() == true)
+      return 1;
+   
+   if (Cache[A].InstVerIter(Cache).FileList().end() == true)
+      return -1;
+   if (Cache[A].InstVerIter(Cache).FileList().end() == true)
+      return 1;
+   
+   pkgCache::PackageFile *FA = Cache[A].InstVerIter(Cache).FileList().File();
+   pkgCache::PackageFile *FB = Cache[B].InstVerIter(Cache).FileList().File();
+   if (FA < FB)
+      return -1;
+   if (FA > FB)
+      return 1;
+   return 0;
+}
+									/*}}}*/
+// OrderList::OrderCompareA - Order the installation by op		/*{{{*/
+// ---------------------------------------------------------------------
+/* This provides a first-pass sort of the list and gives a decent starting
+    point for further complete ordering. It is used by OrderUnpack only */
+int pkgOrderList::OrderCompareA(const void *a, const void *b)
+{
+   PkgIterator A(Me->Cache,*(Package **)a);
+   PkgIterator B(Me->Cache,*(Package **)b);
+
+   if (A.State() != pkgCache::PkgIterator::NeedsNothing && 
+       B.State() == pkgCache::PkgIterator::NeedsNothing)
+      return -1;
+
+   if (A.State() == pkgCache::PkgIterator::NeedsNothing && 
+       B.State() != pkgCache::PkgIterator::NeedsNothing)
+      return 1;
+   
+   int ScoreA = Me->Score(A);
+   int ScoreB = Me->Score(B);
+   if (ScoreA > ScoreB)
+      return -1;
+   
+   if (ScoreA < ScoreB)
+      return 1;
+
+   return strcmp(A.Name(),B.Name());
+}
+									/*}}}*/
+// OrderList::OrderCompareB - Order the installation by source		/*{{{*/
+// ---------------------------------------------------------------------
+/* This orders by installation source. This is usefull to handle
+   inter-source breaks */
+int pkgOrderList::OrderCompareB(const void *a, const void *b)
+{
+   PkgIterator A(Me->Cache,*(Package **)a);
+   PkgIterator B(Me->Cache,*(Package **)b);
+
+   if (A.State() != pkgCache::PkgIterator::NeedsNothing && 
+       B.State() == pkgCache::PkgIterator::NeedsNothing)
+      return -1;
+
+   if (A.State() == pkgCache::PkgIterator::NeedsNothing && 
+       B.State() != pkgCache::PkgIterator::NeedsNothing)
+      return 1;
+   
+   int F = Me->FileCmp(A,B);
+   if (F != 0)
+   {
+      if (F > 0)
+	 return -1;
+      return 1;
+   }
+   
+   int ScoreA = Me->Score(A);
+   int ScoreB = Me->Score(B);
+   if (ScoreA > ScoreB)
+      return -1;
+   
+   if (ScoreA < ScoreB)
+      return 1;
+
+   return strcmp(A.Name(),B.Name());
+}
+									/*}}}*/
+
+// OrderList::VisitDeps - Visit forward install dependencies		/*{{{*/
+// ---------------------------------------------------------------------
+/* This calls the dependency function for the normal forwards dependencies
+   of the package */
+bool pkgOrderList::VisitDeps(DepFunc F,PkgIterator Pkg)
+{
+   if (F == 0 || Pkg.end() == true || Cache[Pkg].InstallVer == 0)
+      return true;
+   
+   return (this->*F)(Cache[Pkg].InstVerIter(Cache).DependsList());
+}
+									/*}}}*/
+// OrderList::VisitRDeps - Visit reverse dependencies			/*{{{*/
+// ---------------------------------------------------------------------
+/* This calls the dependency function for all of the normal reverse depends
+   of the package */
+bool pkgOrderList::VisitRDeps(DepFunc F,PkgIterator Pkg)
+{
+   if (F == 0 || Pkg.end() == true)
+      return true;
+   
+   return (this->*F)(Pkg.RevDependsList());
+}
+									/*}}}*/
+// OrderList::VisitRProvides - Visit provides reverse dependencies	/*{{{*/
+// ---------------------------------------------------------------------
+/* This calls the dependency function for all reverse dependencies
+   generated by the provides line on the package. */
+bool pkgOrderList::VisitRProvides(DepFunc F,VerIterator Ver)
+{
+   if (F == 0 || Ver.end() == true)
+      return true;
+   
+   bool Res = true;
+   for (PrvIterator P = Ver.ProvidesList(); P.end() == false; P++)
+      Res &= (this->*F)(P.ParentPkg().RevDependsList());
+   return true;
+}
+									/*}}}*/
+// OrderList::VisitProvides - Visit all of the providing packages	/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine calls visit on all providing packages. */
+bool pkgOrderList::VisitProvides(DepIterator D)
+{
+   Version **List = D.AllTargets();
+   for (Version **I = List; *I != 0; I++)
+   {
+      VerIterator Ver(Cache,*I);
+      PkgIterator Pkg = Ver.ParentPkg();
+      
+      if (Cache[Pkg].Keep() == true)
+	 continue;
+      
+      if (D->Type != pkgCache::Dep::Conflicts && Cache[Pkg].InstallVer != *I)
+	 continue;
+      
+      if (D->Type == pkgCache::Dep::Conflicts && (Version *)Pkg.CurrentVer() != *I)
+	 continue;
+      
+      if (VisitNode(Pkg) == false)
+      {
+	 delete [] List;
+	 return false;
+      }
+   }
+   delete [] List;
+   return true;
+}
+									/*}}}*/
+// OrderList::VisitNode - Recursive ordering director			/*{{{*/
+// ---------------------------------------------------------------------
+/* This is the core ordering routine. It calls the set dependency
+   consideration functions which then potentialy call this again. Finite
+   depth is achived through the colouring mechinism. */
+bool pkgOrderList::VisitNode(PkgIterator Pkg)
+{
+   // Looping or irrelevent.
+   if (Pkg.end() == true || IsFlag(Pkg,Added) == true || 
+       IsFlag(Pkg,AddPending) == true || IsFlag(Pkg,InList) == false)
+      return true;
+
+/* for (int j = 0; j != Depth; j++) cout << ' ';
+ cout << "Visit " << Pkg.Name() << endl;*/
+   Depth++;
+   
+   // Color grey
+   Flag(Pkg,AddPending);
+
+   DepFunc Old = Primary;
+   
+   // Perform immedate configuration of the package if so flagged.
+   if (IsFlag(Pkg,Immediate) == true && Primary != &DepUnPackPre)
+      Primary = &DepUnPackPreD;
+      
+   bool Res = true;
+   if (Cache[Pkg].Delete() == false)
+   {
+      // Primary
+      Res &= Res && VisitDeps(Primary,Pkg);
+      Res &= Res && VisitRDeps(Primary,Pkg);
+      Res &= Res && VisitRProvides(Primary,Pkg.CurrentVer());
+      Res &= Res && VisitRProvides(Primary,Cache[Pkg].InstVerIter(Cache));
+      
+      // RevDep
+      Res &= Res && VisitRDeps(RevDepends,Pkg);
+      Res &= Res && VisitRProvides(RevDepends,Pkg.CurrentVer());
+      Res &= Res && VisitRProvides(RevDepends,Cache[Pkg].InstVerIter(Cache));
+	
+      // Secondary
+      Res &= Res && VisitDeps(Secondary,Pkg);
+      Res &= Res && VisitRDeps(Secondary,Pkg);
+      Res &= Res && VisitRProvides(Secondary,Pkg.CurrentVer());
+      Res &= Res && VisitRProvides(Secondary,Cache[Pkg].InstVerIter(Cache));
+   }
+   else
+   { 
+      // RevDep
+      Res &= Res && VisitRDeps(Remove,Pkg);
+      Res &= Res && VisitRProvides(Remove,Pkg.CurrentVer());
+   }
+
+   if (IsFlag(Pkg,Added) == false)
+   {
+      Flag(Pkg,Added,Added | AddPending);
+      *End = Pkg;
+      End++;
+   }
+   
+   Primary = Old;
+   Depth--;
+   
+/* for (int j = 0; j != Depth; j++) cout << ' ';
+   cout << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;*/
+
+   return true;
+}
+									/*}}}*/
+
+// OrderList::DepUnPackCrit - Critical UnPacking ordering		/*{{{*/
+// ---------------------------------------------------------------------
+/* Critical unpacking ordering strives to satisfy Conflicts: and 
+   PreDepends: only. When a prdepends is encountered the Primary 
+   DepFunc is changed to be DepUnPackPreD. 
+
+   Loops are preprocessed and logged. */
+bool pkgOrderList::DepUnPackCrit(DepIterator D)
+{
+   for (; D.end() == false; D++)
+   {
+      if (D.Reverse() == true)
+      {
+	 /* Reverse depenanices are only interested in conflicts,
+	    predepend breakage is ignored here */
+	 if (D->Type != pkgCache::Dep::Conflicts)
+	    continue;
+
+	 // Duplication elimination, consider only the current version
+	 if (D.ParentPkg().CurrentVer() != D.ParentVer())
+	    continue;
+	 
+	 /* For reverse dependencies we wish to check if the
+	    dependency is satisifed in the install state. The
+	    target package (caller) is going to be in the installed
+	    state. */
+	 if (CheckDep(D) == true)
+	    continue;
+
+	 if (VisitNode(D.ParentPkg()) == false)
+	    return false;
+      }
+      else
+      {
+	 /* Forward critical dependencies MUST be correct before the 
+	    package can be unpacked. */
+	 if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::PreDepends)
+	    continue;
+	 	 	 	 
+	 /* We wish to check if the dep is okay in the now state of the
+	    target package against the install state of this package. */
+	 if (CheckDep(D) == true)
+	 {
+	    /* We want to catch predepends loops with the code below.
+	       Conflicts loops that are Dep OK are ignored */
+	    if (IsFlag(D.TargetPkg(),AddPending) == false ||
+		D->Type != pkgCache::Dep::PreDepends)
+	       continue;
+	 }
+
+	 // This is the loop detection
+	 if (IsFlag(D.TargetPkg(),Added) == true || 
+	     IsFlag(D.TargetPkg(),AddPending) == true)
+	 {
+	    if (IsFlag(D.TargetPkg(),AddPending) == true)
+	       AddLoop(D);
+	    continue;
+	 }
+
+	 /* Predepends require a special ordering stage, they must have
+	    all dependents installed as well */
+	 DepFunc Old = Primary;
+	 bool Res = false;
+	 if (D->Type == pkgCache::Dep::PreDepends)
+	    Primary = &DepUnPackPreD;
+	 Res = VisitProvides(D);
+	 Primary = Old;
+	 if (Res == false)
+	    return false;
+      }	 
+   }   
+   return true;
+}
+									/*}}}*/
+// OrderList::DepUnPackPreD - Critical UnPacking ordering with depends	/*{{{*/
+// ---------------------------------------------------------------------
+/* Critical PreDepends (also configure immediate and essential) strives to
+   ensure not only that all conflicts+predepends are met but that this
+   package will be immediately configurable when it is unpacked. 
+
+   Loops are preprocessed and logged. */
+bool pkgOrderList::DepUnPackPreD(DepIterator D)
+{
+   if (D.Reverse() == true)
+      return DepUnPackCrit(D);
+   
+   for (; D.end() == false; D++)
+   {
+      if (D.IsCritical() == false)
+	 continue;
+
+      /* We wish to check if the dep is okay in the now state of the
+         target package against the install state of this package. */
+      if (CheckDep(D) == true)
+      {
+	 /* We want to catch predepends loops with the code below.
+	    Conflicts loops that are Dep OK are ignored */
+	 if (IsFlag(D.TargetPkg(),AddPending) == false ||
+	     D->Type != pkgCache::Dep::PreDepends)
+	    continue;
+      }
+      
+      // This is the loop detection
+      if (IsFlag(D.TargetPkg(),Added) == true || 
+	  IsFlag(D.TargetPkg(),AddPending) == true)
+      {
+	 if (IsFlag(D.TargetPkg(),AddPending) == true)
+	    AddLoop(D);
+	 continue;
+      }
+      
+      if (VisitProvides(D) == false)
+	 return false;
+   }   
+   return true;
+}
+									/*}}}*/
+// OrderList::DepUnPackPre - Critical Predepends ordering		/*{{{*/
+// ---------------------------------------------------------------------
+/* Critical PreDepends (also configure immediate and essential) strives to
+   ensure not only that all conflicts+predepends are met but that this
+   package will be immediately configurable when it is unpacked. 
+
+   Loops are preprocessed and logged. All loops will be fatal. */
+bool pkgOrderList::DepUnPackPre(DepIterator D)
+{
+   if (D.Reverse() == true)
+      return true;
+   
+   for (; D.end() == false; D++)
+   {
+      /* Only consider the PreDepends or Depends. Depends are only
+       	 considered at the lowest depth or in the case of immediate
+       	 configure */
+      if (D->Type != pkgCache::Dep::PreDepends)
+      {
+	 if (D->Type == pkgCache::Dep::Depends)
+	 {
+	    if (Depth == 1 && IsFlag(D.ParentPkg(),Immediate) == false)
+	       continue;
+	 }
+	 else
+	    continue;
+      }
+
+      /* We wish to check if the dep is okay in the now state of the
+         target package against the install state of this package. */
+      if (CheckDep(D) == true)
+      {
+	 /* We want to catch predepends loops with the code below.
+	    Conflicts loops that are Dep OK are ignored */
+	 if (IsFlag(D.TargetPkg(),AddPending) == false)
+	    continue;
+      }
+      
+      // This is the loop detection
+      if (IsFlag(D.TargetPkg(),Added) == true || 
+	  IsFlag(D.TargetPkg(),AddPending) == true)
+      {
+	 if (IsFlag(D.TargetPkg(),AddPending) == true)
+	    AddLoop(D);
+	 continue;
+      }
+      
+      if (VisitProvides(D) == false)
+	 return false;
+   }   
+   return true;
+}
+									/*}}}*/
+// OrderList::DepUnPackDep - Reverse dependency considerations		/*{{{*/
+// ---------------------------------------------------------------------
+/* Reverse dependencies are considered to determine if unpacking this
+   package will break any existing dependencies. If so then those
+   packages are ordered before this one so that they are in the
+   UnPacked state. 
+ 
+   The forwards depends loop is designed to bring the packages dependents
+   close to the package. This helps reduce deconfigure time. 
+   
+   Loops are irrelevent to this. */
+bool pkgOrderList::DepUnPackDep(DepIterator D)
+{
+   
+   for (; D.end() == false; D++)
+      if (D.IsCritical() == true)
+      {
+	 if (D.Reverse() == true)
+	 {
+	    /* Duplication prevention. We consider rev deps only on
+	       the current version, a not installed package
+	       cannot break */
+	    if (D.ParentPkg()->CurrentVer == 0 ||
+		D.ParentPkg().CurrentVer() != D.ParentVer())
+	       continue;
+
+	    // The dep will not break so it is irrelevent.
+	    if (CheckDep(D) == true)
+	       continue;
+	    
+	    if (VisitNode(D.ParentPkg()) == false)
+	       return false;
+	 }
+	 else
+	    if (D->Type == pkgCache::Dep::Depends)
+	       if (VisitProvides(D) == false)
+		  return false;
+      }
+   return true;
+}
+									/*}}}*/
+// OrderList::DepConfigure - Configuration ordering			/*{{{*/
+// ---------------------------------------------------------------------
+/* Configuration only ordering orders by the Depends: line only. It
+   orders configuration so that when a package comes to be configured it's
+   dependents are configured. 
+ 
+   Loops are ingored. Depends loop entry points are chaotic. */
+bool pkgOrderList::DepConfigure(DepIterator D)
+{
+   // Never consider reverse configuration dependencies.
+   if (D.Reverse() == true)
+      return true;
+   
+   for (; D.end() == false; D++)
+      if (D->Type == pkgCache::Dep::Depends)
+	 if (VisitProvides(D) == false)
+	    return false;
+   return true;
+}
+									/*}}}*/
+// OrderList::DepRemove - Removal ordering				/*{{{*/
+// ---------------------------------------------------------------------
+/* Removal visits all reverse depends. It considers if the dependency
+   of the Now state version to see if it is okay with removing this
+   package. This check should always fail, but is provided for symetery
+   with the other critical handlers.
+ 
+   Loops are preprocessed and logged. Removal loops can also be
+   detected in the critical handler. They are characterized by an
+   old version of A depending on B but the new version of A conflicting
+   with B, thus either A or B must break to install. */
+bool pkgOrderList::DepRemove(DepIterator D)
+{
+   if (D.Reverse() == false)
+      return true;
+   for (; D.end() == false; D++)
+      if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
+      {
+	 // Duplication elimination, consider the current version only
+	 if (D.ParentPkg().CurrentVer() != D.ParentVer())
+	    continue;
+
+	 /* We wish to see if the dep on the parent package is okay
+	    in the removed (install) state of the target pkg. */	 
+	 if (CheckDep(D) == true)
+	 {
+	    // We want to catch loops with the code below.
+	    if (IsFlag(D.ParentPkg(),AddPending) == false)
+	       continue;
+	 }
+
+	 // This is the loop detection
+	 if (IsFlag(D.ParentPkg(),Added) == true || 
+	     IsFlag(D.ParentPkg(),AddPending) == true)
+	 {
+	    if (IsFlag(D.ParentPkg(),AddPending) == true)
+	       AddLoop(D);
+	    continue;
+	 }
+
+	 if (VisitNode(D.ParentPkg()) == false)
+	    return false;
+      }
+   
+   return true;
+}
+									/*}}}*/
+
+// OrderList::AddLoop - Add a loop to the loop list			/*{{{*/
+// ---------------------------------------------------------------------
+/* We record the loops. This is a relic since loop breaking is done 
+   genericaly as part of the safety routines. */
+bool pkgOrderList::AddLoop(DepIterator D)
+{
+   if (LoopCount < 0 || LoopCount >= 20)
+      return false;  
+   
+   // Skip dups
+   if (LoopCount != 0)
+   {
+      if (Loops[LoopCount - 1].ParentPkg() == D.ParentPkg() ||
+	  Loops[LoopCount - 1].TargetPkg() == D.ParentPkg())
+	 return true;
+   }
+   
+   Loops[LoopCount++] = D;
+   
+   // Mark the packages as being part of a loop.
+   Flag(D.TargetPkg(),Loop);
+   Flag(D.ParentPkg(),Loop);
+   return true;
+}
+									/*}}}*/
+// OrderList::WipeFlags - Unset the given flags from all packages	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgOrderList::WipeFlags(unsigned long F)
+{
+   unsigned long Size = Cache.HeaderP->PackageCount;
+   for (unsigned long I = 0; I != Size; I++)
+      Flags[I] &= ~F;
+}
+									/*}}}*/
+// OrderList::CheckDep - Check a dependency for truth			/*{{{*/
+// ---------------------------------------------------------------------
+/* This performs a complete analysis of the dependency wrt to the
+   current add list. It returns true if after all events are
+   performed it is still true. This sort of routine can be approximated
+   by examining the DepCache, however in convoluted cases of provides
+   this fails to produce a suitable result. */
+bool pkgOrderList::CheckDep(DepIterator D)
+{
+   Version **List = D.AllTargets();
+   for (Version **I = List; *I != 0; I++)
+   {
+      VerIterator Ver(Cache,*I);
+      PkgIterator Pkg = Ver.ParentPkg();
+      
+      /* The meaning of Added and AddPending is subtle. AddPending is
+       	 an indication that the package is looping. Because of the
+       	 way ordering works Added means the package will be unpacked
+       	 before this one and AddPending means after. It is therefore
+       	 correct to ignore AddPending in all cases, but that exposes
+       	 reverse-ordering loops which should be ignore. */
+      if (IsFlag(Pkg,Added) == true || 
+	  (IsFlag(Pkg,AddPending) == true && D.Reverse() == true))
+      {
+	 if (Cache[Pkg].InstallVer != *I)
+	    continue;
+      }
+      else
+	 if ((Version *)Pkg.CurrentVer() != *I || 
+	     Pkg.State() != PkgIterator::NeedsNothing)
+	    continue;
+      
+      delete [] List;
+      
+      /* Conflicts requires that all versions are not present, depends
+         just needs one */
+      if (D->Type != pkgCache::Dep::Conflicts)
+	 return true;
+      else
+	 return false;
+   }
+   delete [] List;
+ 
+   /* Conflicts requires that all versions are not present, depends
+      just needs one */
+   if (D->Type == pkgCache::Dep::Conflicts)
+      return true;
+   return false;
+}
+									/*}}}*/
diff --git a/apt-pkg/orderlist.h b/apt-pkg/orderlist.h
new file mode 100644
index 000000000..0dc8a5038
--- /dev/null
+++ b/apt-pkg/orderlist.h
@@ -0,0 +1,123 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: orderlist.h,v 1.1 1998/07/07 04:17:01 jgg Exp $
+/* ######################################################################
+
+   Order List - Represents and Manipulates an ordered list of packages.
+   
+   A list of packages can be ordered by a number of conflicting criteria
+   each given a specific priority. Each package also has a set of flags
+   indicating some usefull things about it that are derived in the 
+   course of sorting. The pkgPackageManager class uses this class for
+   all of it's installation ordering needs.
+   
+   ##################################################################### */
+									/*}}}*/
+// Header section: pkglib
+#ifndef PKGLIB_ORDERLIST_H
+#define PKGLIB_ORDERLIST_H
+
+#ifdef __GNUG__
+#pragma interface "pkglib/orderlist.h"
+#endif 
+
+#include <pkglib/pkgcache.h>
+
+class pkgDepCache;
+class pkgOrderList
+{
+   protected:
+
+   pkgDepCache &Cache;
+   
+   // Bring some usefull types into the local scope
+   typedef pkgCache::PkgIterator PkgIterator;
+   typedef pkgCache::VerIterator VerIterator;
+   typedef pkgCache::DepIterator DepIterator;
+   typedef pkgCache::PrvIterator PrvIterator;
+   typedef pkgCache::Package Package;
+   typedef pkgCache::Version Version;
+   typedef bool (pkgOrderList::*DepFunc)(DepIterator D);
+
+   // These are the currently selected ordering functions
+   DepFunc Primary;
+   DepFunc Secondary;
+   DepFunc RevDepends;
+   DepFunc Remove;
+
+   // State
+   Package **End;
+   Package **List;
+   DepIterator Loops[20];
+   int LoopCount;
+   int Depth;
+   unsigned char *Flags;
+   
+   // Main visit function
+   bool VisitNode(PkgIterator Pkg);
+   bool VisitDeps(DepFunc F,PkgIterator Pkg);
+   bool VisitRDeps(DepFunc F,PkgIterator Pkg);
+   bool VisitRProvides(DepFunc F,VerIterator Ver);
+   bool VisitProvides(DepIterator Pkg);
+   
+   // Dependency checking functions.
+   bool DepUnPackCrit(DepIterator D);
+   bool DepUnPackPreD(DepIterator D);
+   bool DepUnPackPre(DepIterator D);
+   bool DepUnPackDep(DepIterator D);
+   bool DepConfigure(DepIterator D);
+   bool DepRemove(DepIterator D);
+   
+   // Analysis helpers
+   bool AddLoop(DepIterator D);
+   bool CheckDep(DepIterator D);
+   bool DoRun();
+   
+   // For pre sorting
+   static pkgOrderList *Me;
+   static int OrderCompareA(const void *a, const void *b);
+   static int OrderCompareB(const void *a, const void *b);
+   int FileCmp(PkgIterator A,PkgIterator B);
+   
+   public:
+
+   typedef Package **iterator;
+   
+   // State flags
+   enum Flags {Added = (1 << 0), AddPending = (1 << 1),
+               Immediate = (1 << 2), Loop = (1 << 3),
+               UnPacked = (1 << 4), Configured = (1 << 5),
+               Removed = (1 << 6),
+               InList = (1 << 7),
+               States = (UnPacked | Configured | Removed)};
+
+   // Flag manipulators
+   inline bool IsFlag(PkgIterator Pkg,unsigned long F) {return (Flags[Pkg->ID] & F) == F;};
+   inline bool IsFlag(Package *Pkg,unsigned long F) {return (Flags[Pkg->ID] & F) == F;};
+   void Flag(PkgIterator Pkg,unsigned long State, unsigned long F) {Flags[Pkg->ID] = (Flags[Pkg->ID] & (~F)) | State;};
+   inline void Flag(PkgIterator Pkg,unsigned long F) {Flags[Pkg->ID] |= F;};
+   inline void Flag(Package *Pkg,unsigned long F) {Flags[Pkg->ID] |= F;};
+   inline bool IsNow(PkgIterator Pkg) {return (Flags[Pkg->ID] & States) == 0;};
+   void WipeFlags(unsigned long F);
+   
+   // Accessors
+   inline iterator begin() {return List;};
+   inline iterator end() {return End;};
+   inline void push_back(Package *Pkg) {*(End++) = Pkg;};
+   inline void push_back(PkgIterator Pkg) {*(End++) = Pkg;};
+   inline void pop_back() {End--;};
+   inline bool empty() {return End == List;};
+   inline unsigned int size() {return End - List;};
+   
+   // Ordering modes
+   bool OrderCritical();
+   bool OrderUnpack();
+   bool OrderConfigure();
+
+   int Score(PkgIterator Pkg);
+
+   pkgOrderList(pkgDepCache &Cache);
+   ~pkgOrderList();
+};
+
+#endif
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
new file mode 100644
index 000000000..ebf67b5ee
--- /dev/null
+++ b/apt-pkg/packagemanager.cc
@@ -0,0 +1,548 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: packagemanager.cc,v 1.1 1998/07/07 04:17:01 jgg Exp $
+/* ######################################################################
+
+   Package Manager - Abstacts the package manager
+
+   More work is needed in the area of transitioning provides, ie exim
+   replacing smail. This can cause interesing side effects.
+
+   Other cases involving conflicts+replaces should be tested. 
+   
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/packagemanager.h"
+#endif
+#include <pkglib/packagemanager.h>
+#include <pkglib/orderlist.h>
+#include <pkglib/depcache.h>
+#include <pkglib/sourcelist.h>
+#include <pkglib/aquire.h>
+#include <pkglib/controlcache.h>
+#include <pkglib/error.h>
+#include <options.h>
+									/*}}}*/
+
+// PM::PackageManager - Constructor					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgPackageManager::pkgPackageManager(pkgDepCache &Cache) : Cache(Cache)
+{
+   FileNames = new string[Cache.Head().PackageCount];
+   List = 0;
+}
+									/*}}}*/
+// PM::PackageManager - Destructor					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgPackageManager::~pkgPackageManager()
+{
+   delete List;
+   delete [] FileNames;
+}
+									/*}}}*/
+// PM::GetArchives - Puts the install archives in the aquire list	/*{{{*/
+// ---------------------------------------------------------------------
+/* The Source list is used to convert the packages to install into
+   URNs which are then passed to Aquire to convert to FileNames. */
+bool pkgPackageManager::GetArchives(pkgSourceList &List,pkgAquire &Engine)
+{
+   pkgControlCache CCache(Cache);
+   if (_error->PendingError() == true)
+      return false;
+
+   Engine.OutputDir(PKG_DEB_CA_ARCHIVES);
+   pkgCache::PkgIterator I = Cache.PkgBegin();
+   for (;I.end() != true; I++)
+   {
+      // Not interesting
+      if ((Cache[I].InstallVer == (pkgCache::Version *)I.CurrentVer() &&
+	  I.State() != pkgCache::PkgIterator::NeedsUnpack) ||
+	   Cache[I].Delete() == true)
+	 continue;
+      
+      // Cross match with the source list.
+      pkgSourceList::const_iterator Dist = List.MatchPkgFile(Cache[I].InstVerIter(Cache));
+      if (Dist == List.end())
+      {
+	 _error->Warning("Couldn't locate an archive source for package %s",I.Name());
+	 continue;
+      }
+
+      // Read in the info record
+      pkgSPkgCtrlInfo Inf = CCache[Cache[I].InstVerIter(Cache)];
+      if (Inf.isNull() == true)
+      {
+	 _error->Warning("Couldn't locate info for package %s",I.Name());
+	 continue;
+      }    
+
+      // Isolate the filename
+      string File = Inf->Find("Filename")->Value();
+      if (File.empty() == true)
+      {
+	 _error->Warning("Couldn't locate an archive for package %s",I.Name());
+	 continue;
+      }    
+
+      // Generate the get request.
+      string URI = Dist->ArchiveURI(File);
+      
+      // Output file
+      unsigned int Pos = File.rfind('/');
+      if (Pos == File.length())
+	 return _error->Error("Malformed file line in package %s",I.Name());
+      
+      // Null pos isnt used in present package files
+      if (Pos == string::npos)
+	 Pos = 0;
+      else
+	 Pos++;
+      
+      if (Engine.Get(URI,string(File,Pos),
+		     Dist->ArchiveInfo(Cache[I].InstVerIter(Cache)),
+		     Cache[I].InstVerIter(Cache)->Size,
+		     Inf->Find("MD5sum")->Value(),
+		     &FileNames[I->ID]) == false)
+	    return false;
+   }
+
+   return true;
+}
+									/*}}}*/
+// PM::FixMissing - Keep all missing packages				/*{{{*/
+// ---------------------------------------------------------------------
+/* This is called to correct the installation when packages could not
+   be downloaded. */
+bool pkgPackageManager::FixMissing()
+{
+   unsigned char *Touch = new unsigned char[Cache.Head().PackageCount];
+   for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      // Create the status list that ResolveConflicts needs
+      if ((Cache[I].DepState & pkgDepCache::DepNowMin) == pkgDepCache::DepNowMin)
+	 Touch[I->ID] = (1 << 0) | (1 << 1);
+      else
+	 Touch[I->ID] = 1 << 1;
+      
+      if (Cache[I].Keep() == true)
+	 continue;
+      if (FileNames[I->ID].empty() == false || Cache[I].Delete() == true)
+	 continue;
+      Cache.MarkKeep(I);
+   }
+   
+   // Now downgrade everything that is broken
+   Cache.ResolveConflicts(Touch);
+   delete [] Touch;
+
+   return Cache.BrokenCount() == 0;
+}
+									/*}}}*/
+
+// PM::DepAlwaysTrue - Returns true if this dep is irrelevent		/*{{{*/
+// ---------------------------------------------------------------------
+/* The restriction on provides is to eliminate the case when provides
+   are transitioning between valid states [ie exim to smail] */
+bool pkgPackageManager::DepAlwaysTrue(DepIterator D)
+{
+   if (D.TargetPkg()->ProvidesList != 0)
+      return false;
+   
+   if ((Cache[D] & pkgDepCache::DepInstall) != 0 &&
+       (Cache[D] & pkgDepCache::DepNow) != 0)
+      return true;
+   return false;
+}
+									/*}}}*/
+// PM::CheckRConflicts - Look for reverse conflicts			/*{{{*/
+// ---------------------------------------------------------------------
+/* This looks over the reverses for a conflicts line that needs early
+   removal. */
+bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D,
+					const char *Ver)
+{
+   for (;D.end() == false; D++)
+   {
+      if (D->Type != pkgDEP_Conflicts)
+	 continue;
+      
+      if (D.ParentPkg() == Pkg)
+	 continue;
+      
+      if (pkgCheckDep(D.TargetVer(),Ver,D->CompareOp) == false)
+	 continue;
+
+      if (List->IsNow(Pkg) == false)
+	 continue;
+      
+      if (EarlyRemove(D.ParentPkg()) == false)
+	 return false;
+   }  
+   return true;
+}
+									/*}}}*/
+// PM::ConfigureAll - Run the all out configuration			/*{{{*/
+// ---------------------------------------------------------------------
+/* This configures every package. It is assumed they are all unpacked and
+   that the final configuration is valid. */
+bool pkgPackageManager::ConfigureAll()
+{
+   pkgOrderList OList(Cache);
+   
+   // Populate the order list
+   for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
+      if (List->IsFlag(pkgCache::PkgIterator(Cache,*I),
+		       pkgOrderList::UnPacked) == true)
+	 OList.push_back(*I);
+   
+   if (OList.OrderConfigure() == false)
+      return false;
+   
+   // Perform the configuring
+   for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
+   {
+      PkgIterator Pkg(Cache,*I);
+      
+      if (Configure(Pkg) == false)
+	 return false;
+      
+      List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
+   }
+   
+   return true;
+}
+									/*}}}*/
+// PM::SmartConfigure - Perform immediate configuration of the pkg	/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine scheduals the configuration of the given package and all
+   of it's dependents. */
+bool pkgPackageManager::SmartConfigure(PkgIterator Pkg)
+{
+   pkgOrderList OList(Cache);
+
+   if (DepAdd(OList,Pkg) == false)
+      return false;
+   
+   if (OList.OrderConfigure() == false)
+      return false;
+
+   // Perform the configuring
+   for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
+   {
+      PkgIterator Pkg(Cache,*I);
+      
+      if (Configure(Pkg) == false)
+	 return false;
+      
+      List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
+   }
+
+   // Sanity Check
+   if (List->IsFlag(Pkg,pkgOrderList::Configured) == false)
+      return _error->Error("Internal error, could not immediate configure %s",Pkg.Name());
+   
+   return true;
+}
+									/*}}}*/
+// PM::DepAdd - Add all dependents to the oder list			/*{{{*/
+// ---------------------------------------------------------------------
+/* This recursively adds all dependents to the order list */
+bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth)
+{
+   if (OList.IsFlag(Pkg,pkgOrderList::Added) == true)
+      return true;
+   if (List->IsFlag(Pkg,pkgOrderList::Configured) == true)
+      return true;
+   if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false)
+      return false;
+   
+   
+   // Put the package on the list
+   OList.push_back(Pkg);
+   OList.Flag(Pkg,pkgOrderList::Added);
+   Depth++;
+
+   // Check the dependencies to see if they are all satisfied.
+   bool Bad = false;
+   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
+   {
+      if (D->Type != pkgDEP_Depends && D->Type != pkgDEP_PreDepends)
+      {
+	 D++;
+	 continue;
+      }
+      
+      // Grok or groups
+      Bad = true;
+      for (bool LastOR = true; D.end() == false && LastOR == true; D++)
+      {
+	 LastOR = (D->CompareOp & pkgOP_OR) == pkgOP_OR;
+	 
+	 if (Bad == false)
+	    continue;
+
+	 Version **VList = D.AllTargets();
+	 for (Version **I = VList; *I != 0 && Bad == true; I++)
+	 {
+	    VerIterator Ver(Cache,*I);
+	    PkgIterator Pkg = Ver.ParentPkg();
+
+	    // See if the current version is ok
+	    if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true && 
+		Pkg.State() == PkgIterator::NeedsNothing)
+	    {
+	       Bad = false;
+	       continue;
+	    }
+	    
+	    // Not the install version 
+	    if (Cache[Pkg].InstallVer != *I || 
+		(Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
+	       continue;
+	    if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == true)
+	       Bad = !DepAdd(OList,Pkg,Depth);
+	    if (List->IsFlag(Pkg,pkgOrderList::Configured) == true)
+	       Bad = false;
+	 }
+	 delete [] VList;
+      }
+      
+      if (Bad == true)
+      {
+	 OList.Flag(Pkg,0,pkgOrderList::Added);
+	 OList.pop_back();
+	 Depth--;
+	 return false;
+      }
+   }
+   
+   Depth--;
+   return true;
+}
+									/*}}}*/
+// PM::EarlyRemove - Perform removal of packages before their time	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is called to deal with conflicts arising from unpacking */
+bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
+{
+   if (List->IsNow(Pkg) == false)
+      return true;
+	 
+   // Already removed it
+   if (List->IsFlag(Pkg,pkgOrderList::Removed) == true)
+      return true;
+   
+   // Woops, it will not be re-installed!
+   if (List->IsFlag(Pkg,pkgOrderList::InList) == false)
+      return false;
+   
+   bool Res = SmartRemove(Pkg);
+   if (Cache[Pkg].Delete() == false)
+      List->Flag(Pkg,pkgOrderList::Removed,pkgOrderList::States);
+   
+   return Res;
+}
+									/*}}}*/
+// PM::SmartRemove - Removal Helper					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgPackageManager::SmartRemove(PkgIterator Pkg)
+{
+   if (List->IsNow(Pkg) == false)
+      return true;
+
+   List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
+   return Remove(Pkg);
+}
+									/*}}}*/
+// PM::SmartUnPack - Install helper					/*{{{*/
+// ---------------------------------------------------------------------
+/* This performs the task of handling pre-depends. */
+bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
+{
+   // Check if it is already unpacked
+   if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
+       Cache[Pkg].Keep() == true)
+   {
+      List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States);
+      if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true)
+	 if (SmartConfigure(Pkg) == false)
+	    return _error->Error("Internal Error, Could not perform immediate configuraton");
+      return true;
+   }
+   
+   /* See if this packages install version has any predependencies
+      that are not met by 'now' packages. */
+   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); 
+	D.end() == false; D++)
+   {
+      if (D->Type == pkgDEP_PreDepends)
+      {
+	 // Look for possible ok targets.
+	 Version **VList = D.AllTargets();
+	 bool Bad = true;
+	 for (Version **I = VList; *I != 0 && Bad == true; I++)
+	 {
+	    VerIterator Ver(Cache,*I);
+	    PkgIterator Pkg = Ver.ParentPkg();
+	    
+	    // See if the current version is ok
+	    if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true && 
+		Pkg.State() == PkgIterator::NeedsNothing)
+	    {
+	       Bad = false;
+	       continue;
+	    }
+	 }
+	 
+	 // Look for something that could be configured.
+	 for (Version **I = VList; *I != 0 && Bad == true; I++)
+	 {
+	    VerIterator Ver(Cache,*I);
+	    PkgIterator Pkg = Ver.ParentPkg();
+	    
+	    // Not the install version 
+	    if (Cache[Pkg].InstallVer != *I || 
+		(Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
+	       continue;
+
+	    Bad = !SmartConfigure(Pkg);
+	 }
+	 
+	 delete [] VList;
+	 
+	 if (Bad == true)
+	    return _error->Error("Internal Error, Couldn't configure a pre-depend");
+
+	 continue;
+      }
+      
+      if (D->Type == pkgDEP_Conflicts)
+      {
+	 /* Look for conflicts. Two packages that are both in the install
+	    state cannot conflict so we don't check.. */
+	 Version **VList = D.AllTargets();
+	 for (Version **I = VList; *I != 0; I++)
+	 {
+	    VerIterator Ver(Cache,*I);
+	    PkgIterator Pkg = Ver.ParentPkg();
+	    
+	    // See if the current version is conflicting
+	    if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true)
+	    {
+	       if (EarlyRemove(Pkg) == false)
+		  return _error->Error("Internal Error, Could not early remove %s",Pkg.Name());
+	    }
+	 }
+	 delete [] VList;
+      }
+   }
+
+   // Check for reverse conflicts.
+   CheckRConflicts(Pkg,Pkg.RevDependsList(),
+		   Cache[Pkg].InstVerIter(Cache).VerStr());
+   for (PrvIterator P = Cache[Pkg].InstVerIter(Cache).ProvidesList(); 
+	P.end() == false; P++)
+      CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion());
+   
+   if (Install(Pkg,FileNames[Pkg->ID]) == false)
+      return false;
+   
+   List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States);
+   
+   // Perform immedate configuration of the package.
+   if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true)
+      if (SmartConfigure(Pkg) == false)
+	 return _error->Error("Internal Error, Could not perform immediate configuraton");
+   
+   return true;
+}
+									/*}}}*/
+// PM::OrderInstall - Installation ordering routine			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgPackageManager::OrderInstall()
+{
+   delete List;
+   List = new pkgOrderList(Cache);
+   
+   // Generate the list of affected packages and sort it
+   for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
+      // Consider all depends
+      if ((I->Flags & pkgFLAG_Essential) == pkgFLAG_Essential)
+      {
+	 List->Flag(I,pkgOrderList::Immediate);
+	 if (Cache[I].InstallVer != 0)
+	    for (DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); 
+		 D.end() == false; D++)
+	       if (D->Type == pkgDEP_Depends || D->Type == pkgDEP_PreDepends)
+		  List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+	 if (I->CurrentVer != 0)
+	    for (DepIterator D = I.CurrentVer().DependsList(); 
+		 D.end() == false; D++)
+	       if (D->Type == pkgDEP_Depends || D->Type == pkgDEP_PreDepends)
+		  List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+      }
+      
+      // Not interesting
+      if ((Cache[I].Keep() == true || 
+	  Cache[I].InstVerIter(Cache) == I.CurrentVer()) && 
+	  I.State() == pkgCache::PkgIterator::NeedsNothing)
+	 continue;
+      
+      // Append it to the list
+      List->push_back(I);
+      
+      if ((I->Flags & pkgFLAG_ImmediateConf) == pkgFLAG_ImmediateConf)
+	 List->Flag(I,pkgOrderList::Immediate);
+   }
+   
+   if (List->OrderUnpack() == false)
+      return _error->Error("Internal ordering error");
+
+   for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
+   {
+      PkgIterator Pkg(Cache,*I);
+      
+      // Sanity check
+      if (Cache[Pkg].Keep() == true && Pkg.State() == pkgCache::PkgIterator::NeedsNothing)
+	 return _error->Error("Internal Error, trying to manipulate a kept package");
+      
+      // Perform a delete or an install
+      if (Cache[Pkg].Delete() == true)
+      {
+	 if (SmartRemove(Pkg) == false)
+	    return false;	 
+      }
+      else
+	 if (SmartUnPack(Pkg) == false)
+	    return false;
+   }
+   
+   // Final run through the configure phase
+   if (ConfigureAll() == false)
+      return false;
+
+   // Sanity check
+   for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
+      if (List->IsFlag(*I,pkgOrderList::Configured) == false)
+	 return _error->Error("Internal error, packages left unconfigured. %s",
+			      PkgIterator(Cache,*I).Name());
+
+   return true;
+}
+									/*}}}*/
+// PM::DoInstall - Does the installation				/*{{{*/
+// ---------------------------------------------------------------------
+/* This uses the filenames in FileNames and the information in the
+   DepCache to perform the installation of packages.*/
+bool pkgPackageManager::DoInstall()
+{
+   return OrderInstall() && Go();
+}
+									/*}}}*/
diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h
new file mode 100644
index 000000000..6020cbefd
--- /dev/null
+++ b/apt-pkg/packagemanager.h
@@ -0,0 +1,84 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: packagemanager.h,v 1.1 1998/07/07 04:17:01 jgg Exp $
+/* ######################################################################
+
+   Package Manager - Abstacts the package manager
+
+   Three steps are 
+     - Aquiration of archives (stores the list of final file names)
+     - Sorting of operations
+     - Inokation of package manager
+   
+   This is the final stage when the package cache entities get converted
+   into file names and the state stored in a DepCache is transformed
+   into a series of operations.
+
+   In the final scheme of things this may serve as a director class to
+   access the actual install methods based on the file type being
+   installed.
+   
+   ##################################################################### */
+									/*}}}*/
+// Header section: pkglib
+#ifndef PKGLIB_PACKAGEMANAGER_H
+#define PKGLIB_PACKAGEMANAGER_H
+
+#ifdef __GNUG__
+#pragma interface "pkglib/packagemanager.h"
+#endif
+
+#include <string>
+#include <pkglib/pkgcache.h>
+
+class pkgAquire;
+class pkgDepCache;
+class pkgSourceList;
+class pkgOrderList;
+class pkgPackageManager
+{
+   protected:
+   string *FileNames;
+   pkgDepCache &Cache;
+   pkgOrderList *List;
+   
+   // Bring some usefull types into the local scope
+   typedef pkgCache::PkgIterator PkgIterator;
+   typedef pkgCache::VerIterator VerIterator;
+   typedef pkgCache::DepIterator DepIterator;
+   typedef pkgCache::PrvIterator PrvIterator;
+   typedef pkgCache::Version Version;
+   typedef pkgCache::Package Package;
+      
+   bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
+   bool OrderInstall();
+   bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver);
+   
+   // Analysis helpers
+   bool DepAlwaysTrue(DepIterator D);
+   
+   // Install helpers
+   bool ConfigureAll();
+   bool SmartConfigure(PkgIterator Pkg);
+   bool SmartUnPack(PkgIterator Pkg);
+   bool SmartRemove(PkgIterator Pkg);
+   bool EarlyRemove(PkgIterator Pkg);   
+   
+   // The Actuall installation implementation
+   virtual bool Install(PkgIterator /*Pkg*/,string /*File*/) {return false;};
+   virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
+   virtual bool Remove(PkgIterator /*Pkg*/) {return false;};
+   virtual bool Go() {return false;};
+   
+   public:
+
+   // The three stages
+   bool GetArchives(pkgSourceList &List,pkgAquire &Engine);
+   bool DoInstall();
+   bool FixMissing();
+   
+   pkgPackageManager(pkgDepCache &Cache);
+   virtual ~pkgPackageManager();
+};
+
+#endif
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index b9dbf34ec..085225031 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: pkgcache.cc,v 1.4 1998/07/05 05:33:53 jgg Exp $
+// $Id: pkgcache.cc,v 1.5 1998/07/07 04:17:02 jgg Exp $
 /* ######################################################################
    
    Package Cache - Accessor code for the cache
@@ -20,6 +20,10 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/pkgcache.h"
+#pragma implementation "pkglib/cacheiterators.h"
+#endif 
 #include <pkglib/pkgcache.h>
 #include <pkglib/version.h>
 #include <pkglib/error.h>
@@ -199,13 +203,13 @@ void pkgCache::PkgIterator::operator ++(int)
 /* By this we mean if it is either cleanly installed or cleanly removed. */
 pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
 {
-   if (Pkg->CurrentState == UnPacked ||
-       Pkg->CurrentState == HalfConfigured)
+   if (Pkg->CurrentState == State::UnPacked ||
+       Pkg->CurrentState == State::HalfConfigured)
       return NeedsConfigure;
    
-   if (Pkg->CurrentState == UnInstalled ||
-       Pkg->CurrentState == HalfInstalled ||
-       Pkg->InstState != Ok)
+   if (Pkg->CurrentState == State::UnInstalled ||
+       Pkg->CurrentState == State::HalfInstalled ||
+       Pkg->InstState != State::Ok)
       return NeedsUnpack;
       
    return NeedsNothing;
@@ -217,8 +221,8 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
    conflicts. */
 bool pkgCache::DepIterator::IsCritical()
 {
-   if (Dep->Type == Conflicts || Dep->Type == Depends ||
-       Dep->Type == PreDepends)
+   if (Dep->Type == Dep::Conflicts || Dep->Type == Dep::Depends ||
+       Dep->Type == Dep::PreDepends)
       return true;
    return false;
 }
@@ -293,7 +297,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
 	 if (pkgCheckDep(TargetVer(),I.VerStr(),Dep->CompareOp) == false)
 	    continue;
 
-	 if (Dep->Type == Conflicts && ParentPkg() == I.ParentPkg())
+	 if (Dep->Type == Dep::Conflicts && ParentPkg() == I.ParentPkg())
 	    continue;
 	 
 	 Size++;
@@ -307,7 +311,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
 	 if (pkgCheckDep(TargetVer(),I.ProvideVersion(),Dep->CompareOp) == false)
 	    continue;
 	 
-	 if (Dep->Type == Conflicts && ParentPkg() == I.OwnerPkg())
+	 if (Dep->Type == Dep::Conflicts && ParentPkg() == I.OwnerPkg())
 	    continue;
 	 
 	 Size++;
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index 836418c2c..852949b1f 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: pkgcache.h,v 1.4 1998/07/05 05:33:55 jgg Exp $
+// $Id: pkgcache.h,v 1.5 1998/07/07 04:17:03 jgg Exp $
 /* ######################################################################
    
    Cache - Structure definitions for the cache file
@@ -20,6 +20,10 @@
 #ifndef PKGLIB_PKGCACHE_H
 #define PKGLIB_PKGCACHE_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/pkgcache.h"
+#endif 
+
 #include <string>
 #include <time.h>
 #include <pkglib/mmap.h>
@@ -52,19 +56,29 @@ class pkgCache
    friend VerFileIterator;
    
    // These are all the constants used in the cache structures
-   enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
-                 Conflicts=5,Replaces=6};
-   enum VerPriority {Important=1,Required=2,Standard=3,Optional=5,Extra=5};
-   enum PkgSelectedState {Unknown=0,Install=1,Hold=2,DeInstall=3,Purge=4};
-   enum PkgFlags {Auto=(1<<0),New=(1<<1),Obsolete=(1<<2),Essential=(1<<3),
-                  ImmediateConf=(1<<4)};
-   enum PkgInstState {Ok=0,ReInstReq=1,HoldInst=2,HoldReInstReq=3};
-   enum PkgCurrentState {NotInstalled=0,UnPacked=1,HalfConfigured=2,
-                         UnInstalled=3,HalfInstalled=4,ConfigFiles=5,
-                         Installed=6};
-   enum PkgFFlags {NotSource=(1<<0)};
-   enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
-                      Greater=0x4,Equals=0x5,NotEquals=0x6};
+   struct Dep
+   {
+      enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
+	 Conflicts=5,Replaces=6};
+      enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
+	 Greater=0x4,Equals=0x5,NotEquals=0x6};
+   };
+   
+   struct State
+   {
+      enum VerPriority {Important=1,Required=2,Standard=3,Optional=5,Extra=5};
+      enum PkgSelectedState {Unknown=0,Install=1,Hold=2,DeInstall=3,Purge=4};
+      enum PkgInstState {Ok=0,ReInstReq=1,HoldInst=2,HoldReInstReq=3};
+      enum PkgCurrentState {NotInstalled=0,UnPacked=1,HalfConfigured=2,
+	 UnInstalled=3,HalfInstalled=4,ConfigFiles=5,Installed=6};
+   };
+   
+   struct Flag
+   {
+      enum PkgFlags {Auto=(1<<0),New=(1<<1),Obsolete=(1<<2),Essential=(1<<3),
+	 ImmediateConf=(1<<4)};
+      enum PkgFFlags {NotSource=(1<<0)};
+   };
    
    protected:
    
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index acc05f133..aac3f77d9 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: pkgcachegen.cc,v 1.6 1998/07/05 05:53:52 jgg Exp $
+// $Id: pkgcachegen.cc,v 1.7 1998/07/07 04:17:04 jgg Exp $
 /* ######################################################################
    
    Package Cache Generator - Generator for the cache structure.
@@ -10,6 +10,10 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/pkgcachegen.h"
+#endif
+
 #include <pkglib/pkgcachegen.h>
 #include <pkglib/error.h>
 #include <pkglib/version.h>
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index 395afdc83..c883828eb 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: pkgcachegen.h,v 1.3 1998/07/05 05:33:57 jgg Exp $
+// $Id: pkgcachegen.h,v 1.4 1998/07/07 04:17:05 jgg Exp $
 /* ######################################################################
    
    Package Cache Generator - Generator for the cache structure.
@@ -13,6 +13,10 @@
 #ifndef PKGLIB_PKGCACHEGEN_H
 #define PKGLIB_PKGCACHEGEN_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/pkgcachegen.h"
+#endif 
+
 #include <pkglib/pkgcache.h>
 
 class pkgCacheGenerator
diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc
new file mode 100644
index 000000000..62d5e6fcd
--- /dev/null
+++ b/apt-pkg/sourcelist.cc
@@ -0,0 +1,465 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: sourcelist.cc,v 1.1 1998/07/07 04:17:06 jgg Exp $
+/* ######################################################################
+
+   List of Sources
+   
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/sourcelist.h"
+#endif
+
+#include <pkglib/sourcelist.h>
+#include <pkglib/error.h>
+#include <pkglib/fileutl.h>
+#include <strutl.h>
+#include <options.h>
+
+#include <fstream.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+									/*}}}*/
+
+// SourceList::pkgSourceList - Constructors				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgSourceList::pkgSourceList()
+{
+}
+
+pkgSourceList::pkgSourceList(string File)
+{
+   Read(File);
+}
+									/*}}}*/
+// SourceList::ReadMainList - Read the main source list from etc	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSourceList::ReadMainList()
+{
+   return Read(PKG_DEB_CF_SOURCELIST);
+}
+									/*}}}*/
+// SourceList::Read - Parse the sourcelist file				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSourceList::Read(string File)
+{
+   // Open the stream for reading
+   ifstream F(File.c_str(),ios::in | ios::nocreate);
+   if (!F != 0)
+      return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
+   
+   List.erase(List.begin(),List.end());
+   char Buffer[300];
+
+   int CurLine = 0;
+   while (F.eof() == false)
+   {
+      F.getline(Buffer,sizeof(Buffer));
+      CurLine++;
+      _strtabexpand(Buffer,sizeof(Buffer));
+      _strstrip(Buffer);
+      
+      // Comment or blank
+      if (Buffer[0] == '#' || Buffer[0] == 0)
+	 continue;
+      
+      // Grok it
+      string Type;
+      string URI;
+      Item Itm;
+      char *C = Buffer;
+      if (ParseQuoteWord(C,Type) == false)
+	 return _error->Error("Malformed line %u in source list %s (type)",CurLine,File.c_str());
+      if (ParseQuoteWord(C,URI) == false)
+	 return _error->Error("Malformed line %u in source list %s (URI)",CurLine,File.c_str());
+      if (ParseQuoteWord(C,Itm.Dist) == false)
+	 return _error->Error("Malformed line %u in source list %s (dist)",CurLine,File.c_str());
+      if (Itm.SetType(Type) == false)
+	 return _error->Error("Malformed line %u in source list %s (type parse)",CurLine,File.c_str());
+      if (Itm.SetURI(URI) == false)
+	 return _error->Error("Malformed line %u in source list %s (URI parse)",CurLine,File.c_str());
+
+      // Check for an absolute dists specification.
+      if (Itm.Dist.empty() == false && Itm.Dist[Itm.Dist.size() - 1] == '/')
+      {
+	 if (ParseQuoteWord(C,Itm.Section) == true)
+	    return _error->Error("Malformed line %u in source list %s (Absolute dist)",CurLine,File.c_str());
+	 Itm.Dist = SubstVar(Itm.Dist,"$(ARCH)",PKG_DEB_ARCH);
+	 List.push_back(Itm);
+	 continue;
+      }
+
+      // Grab the rest of the dists
+      if (ParseQuoteWord(C,Itm.Section) == false)
+	    return _error->Error("Malformed line %u in source list %s (dist parse)",CurLine,File.c_str());
+      
+      do
+      {
+	 List.push_back(Itm);
+      }
+      while (ParseQuoteWord(C,Itm.Section) == true);
+   }
+   return true;
+}
+									/*}}}*/
+// SourceList::SanitizeURI - Hash the uri				/*{{{*/
+// ---------------------------------------------------------------------
+/* This converts a URI into a safe filename. It quotes all unsafe characters
+   and converts / to _ and removes the scheme identifier. */
+string pkgSourceList::SanitizeURI(string URI)
+{
+   string::const_iterator I = URI.begin() + URI.find(':') + 1;
+   for (; I < URI.end() && *I == '/'; I++);
+
+   // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
+   URI = QuoteString(string(I,URI.end() - I),"\\|{}[]<>\"^~_=!@#$%^&*");
+   string::iterator J = URI.begin();
+   for (; J != URI.end(); J++)
+      if (*J == '/') 
+	 *J = '_';
+   return URI;
+}
+									/*}}}*/
+// SourceList::MatchPkgFile - Find the package file that has the ver	/*{{{*/
+// ---------------------------------------------------------------------
+/* This will return List.end() if it could not find the matching 
+   file */
+pkgSourceList::const_iterator pkgSourceList::MatchPkgFile(pkgCache::VerIterator Ver)
+{
+   string Base = PKG_DEB_ST_LIST;
+   for (const_iterator I = List.begin(); I != List.end(); I++)
+   {
+      string URI = I->PackagesURI();
+      switch (I->Type)
+      {
+	 case Item::Deb:
+	 if (Base + SanitizeURI(URI) == Ver.File().FileName())
+	    return I;
+	 break;
+      };      
+   }
+   return List.end();
+}
+									/*}}}*/
+// SourceList::Item << - Writes the item to a stream			/*{{{*/
+// ---------------------------------------------------------------------
+/* This is not suitable for rebuilding the sourcelist file but it good for
+   debugging. */
+ostream &operator <<(ostream &O,pkgSourceList::Item &Itm)
+{
+   O << Itm.Type << ' ' << Itm.URI << ' ' << Itm.Dist << ' ' << Itm.Section;
+   return O;
+}
+									/*}}}*/
+// SourceList::Item::SetType - Sets the distribution type		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSourceList::Item::SetType(string S)
+{
+   if (S == "deb")
+   {
+      Type = Deb;
+      return true;
+   }
+
+   return true;
+}
+									/*}}}*/
+// SourceList::Item::SetURI - Set the URI				/*{{{*/
+// ---------------------------------------------------------------------
+/* For simplicity we strip the scheme off the uri */
+bool pkgSourceList::Item::SetURI(string S)
+{
+   if (S.empty() == true)
+      return false;
+
+   if (S.find(':') == string::npos)
+      return false;
+
+   S = SubstVar(S,"$(ARCH)",PKG_DEB_ARCH);
+   
+   // Make sure that the URN is / postfixed
+   URI = S;
+   if (URI[URI.size() - 1] != '/')
+      URI += '/';
+   
+   return true;
+}
+									/*}}}*/
+// SourceList::Item::PackagesURI - Returns a URI to the packages file	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string pkgSourceList::Item::PackagesURI() const
+{
+   string Res;
+   switch (Type)
+   {
+      case Deb:
+      if (Dist[Dist.size() - 1] == '/')
+	 Res = URI + Dist;
+      else
+	 Res = URI + "dists/" + Dist + '/' + Section + 
+	 "/binary-" + PKG_DEB_ARCH + '/';
+      
+      Res += "Packages";
+      break;
+   };
+   return Res;
+}
+									/*}}}*/
+// SourceList::Item::PackagesInfo - Shorter version of the URI		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is a shorter version that is designed to be < 60 chars or so */
+string pkgSourceList::Item::PackagesInfo() const
+{
+   string Res;
+   switch (Type)
+   {
+      case Deb:
+      Res += SiteOnly(URI) + ' ';
+      if (Dist[Dist.size() - 1] == '/')
+	 Res += Dist;
+      else
+	 Res += Dist + '/' + Section;
+      
+      Res += " Packages";
+      break;
+   };
+   return Res;
+}
+									/*}}}*/
+// SourceList::Item::ArchiveInfo - Shorter version of the archive spec	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is a shorter version that is designed to be < 60 chars or so */
+string pkgSourceList::Item::ArchiveInfo(pkgCache::VerIterator Ver) const
+{
+   string Res;
+   switch (Type)
+   {
+      case Deb:
+      Res += SiteOnly(URI) + ' ';
+      if (Dist[Dist.size() - 1] == '/')
+	 Res += Dist;
+      else
+	 Res += Dist + '/' + Section;
+      
+      Res += " ";
+      Res += Ver.ParentPkg().Name();
+      break;
+   };
+   return Res;
+}
+									/*}}}*/
+// SourceList::Item::ArchiveURI - Returns a URI to the given archive	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string pkgSourceList::Item::ArchiveURI(string File) const
+{
+   string Res;
+   switch (Type)
+   {
+      case Deb:
+      Res = URI + File;
+      break;
+   };
+   return Res;
+}
+									/*}}}*/
+// SourceList::Item::SiteOnly - Strip off the path part of a URI	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string pkgSourceList::Item::SiteOnly(string URI) const
+{
+   unsigned int Pos = URI.find(':');
+   if (Pos == string::npos || Pos + 3 > URI.length())
+      return URI;
+   if (URI[Pos + 1] != '/' || URI[Pos + 2] != '/')
+      return URI;
+
+   Pos = URI.find('/',Pos + 3);
+   if (Pos == string::npos)
+      return URI;
+   return string(URI,0,Pos);
+}
+									/*}}}*/
+
+// UpdateMeta - Update the meta information				/*{{{*/
+// ---------------------------------------------------------------------
+/* The meta information is package files, revision information and mirror
+   lists. */
+bool pkgUpdateMeta(pkgSourceList &List,pkgAquire &Engine)
+{
+   if (Engine.OutputDir(PKG_DEB_ST_LIST) == false)
+      return false;
+   
+   for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); I++)
+   {
+      string URI = I->PackagesURI();
+      string GetInfo = I->PackagesInfo();
+      switch (I->Type)
+      {
+	 case pkgSourceList::Item::Deb:
+	    if (Engine.Get(URI + ".gz",List.SanitizeURI(URI),GetInfo) == false)
+	       return false;
+	 break;
+      };      
+   }
+   
+   return true;
+}
+									/*}}}*/
+// MakeSrcCache - Generate a cache file of all the package files	/*{{{*/
+// ---------------------------------------------------------------------
+/* This goes over the source list and builds a cache of all the package
+   files. */
+bool pkgMakeSrcCache(pkgSourceList &List)
+{
+   // First we date check the cache
+   bool Bad = false;
+   while (Bad == false)
+   {
+      if (FileExists(PKG_DEB_CA_SRCCACHE) == false)
+	  break;
+	  
+      pkgCache Cache(PKG_DEB_CA_SRCCACHE,true,true);
+      if (_error->PendingError() == true)
+      {
+	 _error->Discard();
+	 break;
+      }
+      
+      // They are certianly out of sync
+      if (Cache.Head().PackageFileCount != List.size())
+	  break;
+      
+      for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
+      {
+	 // Search for a match in the source list
+	 Bad = true;
+	 for (pkgSourceList::const_iterator I = List.begin(); 
+	      I != List.end(); I++)
+	 {
+	    string File = string(PKG_DEB_ST_LIST) + 
+	       List.SanitizeURI(I->PackagesURI());
+	    if (F.FileName() == File)
+	    {
+	       Bad = false;
+	       break;
+	    }
+	 }
+	 
+	 // Check if the file matches what was cached
+	 Bad |= !F.IsOk();
+	 if (Bad == true)
+	    break;
+      }      
+
+      if (Bad == false)
+	 return true;
+   }
+   
+   unlink(PKG_DEB_CA_SRCCACHE);
+   pkgCache::MergeState Merge(PKG_DEB_CA_SRCCACHE);
+   if (_error->PendingError() == true)
+            return false;
+   
+   for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); I++)
+   {
+      string File = string(PKG_DEB_ST_LIST) + List.SanitizeURI(I->PackagesURI());
+      if (Merge.MergePackageFile(File,"??","??") == false)
+	 return false;
+   }
+          
+   return true;
+}
+									/*}}}*/
+// MakeStatusCache - Generates a cache that includes the status files	/*{{{*/
+// ---------------------------------------------------------------------
+/* This copies the package source cache and then merges the status and 
+   xstatus files into it. */
+bool pkgMakeStatusCache()
+{
+   // Quickly check if the existing package cache is ok
+   bool Bad = false;
+   while (Bad == false)
+   {
+      if (FileExists(PKG_DEB_CA_PKGCACHE) == false)
+	  break;
+      
+      /* We check the dates of the two caches. This takes care of most things
+         quickly and easially */
+      struct stat Src;
+      struct stat Pkg;
+      if (stat(PKG_DEB_CA_PKGCACHE,&Pkg) != 0 || 
+	  stat(PKG_DEB_CA_SRCCACHE,&Src) != 0)
+	 break;
+      if (difftime(Src.st_mtime,Pkg.st_mtime) > 0)
+	 break;
+
+      pkgCache Cache(PKG_DEB_CA_PKGCACHE,true,true);
+      if (_error->PendingError() == true)
+      {
+	 _error->Discard();
+	 break;
+      }
+      
+      for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
+      {
+	 if (F.IsOk() == false)
+	 {
+	    Bad = true;
+	    break;
+	 }
+      }
+      
+      if (Bad == false)
+	 return true;
+   }   
+
+   // Check the integrity of the source cache.
+   {
+      pkgCache Cache(PKG_DEB_CA_SRCCACHE,true,true);
+      if (_error->PendingError() == true)
+	 return false;
+   }
+   
+   // Sub scope so that merge destructs before we rename the file...
+   string Cache = PKG_DEB_CA_PKGCACHE ".new";
+   {
+      if (CopyFile(PKG_DEB_CA_SRCCACHE,Cache) == false)
+	 return false;
+
+      pkgCache::MergeState Merge(Cache);
+      if (_error->PendingError() == true)
+	 return false;
+      
+      // Merge in the user status file
+      if (FileExists(PKG_DEB_ST_USERSTATUS) == true)
+	 if (Merge.MergePackageFile(PKG_DEB_ST_USERSTATUS,"status","0",
+				    pkgFLAG_NotSource) == false)
+	    return false;
+      
+      // Merge in the extra status file
+      if (FileExists(PKG_DEB_ST_XSTATUS) == true)
+	 if (Merge.MergePackageFile(PKG_DEB_ST_XSTATUS,"status","0",
+				    pkgFLAG_NotSource) == false)
+	    return false;
+      
+      // Merge in the status file
+      if (Merge.MergePackageFile("/var/lib/dpkg/status","status","0",
+				 pkgFLAG_NotSource) == false)
+	 return false;
+   }
+   
+   if (rename(Cache.c_str(),PKG_DEB_CA_PKGCACHE) != 0)
+      return false;
+   
+   return true;
+}
+									/*}}}*/
diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h
new file mode 100644
index 000000000..986d5e9e8
--- /dev/null
+++ b/apt-pkg/sourcelist.h
@@ -0,0 +1,78 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: sourcelist.h,v 1.1 1998/07/07 04:17:06 jgg Exp $
+/* ######################################################################
+
+   SourceList - Manage a list of sources
+   
+   The Source List class provides access to a list of sources. It 
+   can read them from a file and generate a list of all the permutations.
+   
+   ##################################################################### */
+									/*}}}*/
+// Header section: pkglib
+#ifndef PKGLIB_SOURCELIST_H
+#define PKGLIB_SOURCELIST_H
+
+#include <string>
+#include <vector>
+#include <iostream.h>
+#include <pkglib/pkgcache.h>
+
+#ifdef __GNUG__
+#pragma interface "pkglib/sourcelist.h"
+#endif
+
+class pkgAquire;
+class pkgSourceList
+{
+   public:
+   
+   /* Each item in the source list, each line can have more than one
+      item */
+   struct Item
+   {
+      enum {Deb} Type;
+
+      string URI;
+      string Dist;
+      string Section;
+      
+      bool SetType(string S);
+      bool SetURI(string S);
+      string PackagesURI() const;
+      string PackagesInfo() const;      
+      string SiteOnly(string URI) const;
+      string ArchiveInfo(pkgCache::VerIterator Ver) const;
+      string ArchiveURI(string File) const;
+   };
+   typedef vector<Item>::const_iterator const_iterator;
+   
+   protected:
+   
+   vector<Item> List;
+   
+   public:
+
+   bool ReadMainList();
+   bool Read(string File);
+   string SanitizeURI(string URI);
+   const_iterator MatchPkgFile(pkgCache::VerIterator Ver);
+   
+   // List accessors
+   inline const_iterator begin() const {return List.begin();};
+   inline const_iterator end() const {return List.end();};
+   inline unsigned int size() const {return List.size();};
+   inline bool empty() const {return List.empty();};
+   
+   pkgSourceList();
+   pkgSourceList(string File);   
+};
+
+bool pkgUpdateMeta(pkgSourceList &List,pkgAquire &Engine);
+bool pkgMakeSrcCache(pkgSourceList &List);
+bool pkgMakeStatusCache();
+
+ostream &operator <<(ostream &O,pkgSourceList::Item &Itm);
+
+#endif
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index 9710b7615..b8845a3b1 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: tagfile.cc,v 1.4 1998/07/05 05:33:58 jgg Exp $
+// $Id: tagfile.cc,v 1.5 1998/07/07 04:17:06 jgg Exp $
 /* ######################################################################
 
    Fast scanner for RFC-822 type header information
@@ -11,6 +11,10 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/tagfile.h"
+#endif
+
 #include <pkglib/tagfile.h>
 #include <pkglib/error.h>
 
diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h
index 661ac4f23..c1fffcf13 100644
--- a/apt-pkg/tagfile.h
+++ b/apt-pkg/tagfile.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: tagfile.h,v 1.2 1998/07/05 05:33:59 jgg Exp $
+// $Id: tagfile.h,v 1.3 1998/07/07 04:17:07 jgg Exp $
 /* ######################################################################
 
    Fast scanner for RFC-822 type header information
@@ -21,6 +21,10 @@
 #ifndef PKGLIB_TAGFILE_H
 #define PKGLIB_TAGFILE_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/tagfile.h"
+#endif 
+
 #include <pkglib/fileutl.h>
 
 class pkgTagSection
diff --git a/apt-pkg/version.cc b/apt-pkg/version.cc
index 174622c91..7eb85726c 100644
--- a/apt-pkg/version.cc
+++ b/apt-pkg/version.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: version.cc,v 1.2 1998/07/04 05:57:40 jgg Exp $
+// $Id: version.cc,v 1.3 1998/07/07 04:17:08 jgg Exp $
 /* ######################################################################
 
    Version - Version string 
@@ -17,6 +17,10 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "pkglib/version.h"
+#endif 
+
 #include <pkglib/version.h>
 #include <pkglib/pkgcache.h>
 
@@ -212,32 +216,32 @@ bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op)
    int Res = pkgVersionCompare(PkgVer,DepVer);
    switch (Op & 0x0F)
    {
-      case pkgCache::LessEq:
+      case pkgCache::Dep::LessEq:
       if (Res <= 0)
 	 return true;
       break;
       
-      case pkgCache::GreaterEq:
+      case pkgCache::Dep::GreaterEq:
       if (Res >= 0)
 	 return true;
       break;
       
-      case pkgCache::Less:
+      case pkgCache::Dep::Less:
       if (Res < 0)
 	 return true;
       break;
       
-      case pkgCache::Greater:
+      case pkgCache::Dep::Greater:
       if (Res > 0)
 	 return true;
       break;
       
-      case pkgCache::Equals:
+      case pkgCache::Dep::Equals:
       if (Res == 0)
 	 return true;
       break;
       
-      case pkgCache::NotEquals:
+      case pkgCache::Dep::NotEquals:
       if (Res != 0)
 	 return true;
       break;
diff --git a/apt-pkg/version.h b/apt-pkg/version.h
index a30246946..3ced5d3e4 100644
--- a/apt-pkg/version.h
+++ b/apt-pkg/version.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: version.h,v 1.1 1998/07/02 02:58:13 jgg Exp $
+// $Id: version.h,v 1.2 1998/07/07 04:17:09 jgg Exp $
 /* ######################################################################
 
    Version - Version string 
@@ -15,6 +15,10 @@
 #ifndef PKGLIB_VERSION_H
 #define PKGLIB_VERSION_H
 
+#ifdef __GNUG__
+#pragma interface "pkglib/version.h"
+#endif 
+
 #include <string>
 
 class pkgVersion
-- 
2.47.2