]> git.saurik.com Git - apt.git/commitdiff
* merged apt--no-pragma
authorMichael Vogt <michael.vogt@ubuntu.com>
Sat, 9 Jun 2007 00:08:36 +0000 (02:08 +0200)
committerMichael Vogt <michael.vogt@ubuntu.com>
Sat, 9 Jun 2007 00:08:36 +0000 (02:08 +0200)
41 files changed:
1  2 
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/acquire-method.cc
apt-pkg/acquire-method.h
apt-pkg/acquire-worker.cc
apt-pkg/acquire.cc
apt-pkg/acquire.h
apt-pkg/algorithms.cc
apt-pkg/cacheiterators.h
apt-pkg/cdrom.cc
apt-pkg/cdrom.h
apt-pkg/contrib/cdromutl.h
apt-pkg/contrib/progress.cc
apt-pkg/contrib/sha256.h
apt-pkg/contrib/strutl.cc
apt-pkg/contrib/strutl.h
apt-pkg/deb/debindexfile.cc
apt-pkg/deb/debindexfile.h
apt-pkg/deb/debmetaindex.cc
apt-pkg/deb/debrecords.cc
apt-pkg/deb/debrecords.h
apt-pkg/deb/debsrcrecords.cc
apt-pkg/deb/debsrcrecords.h
apt-pkg/deb/dpkgpm.cc
apt-pkg/deb/dpkgpm.h
apt-pkg/depcache.cc
apt-pkg/depcache.h
apt-pkg/indexfile.cc
apt-pkg/indexfile.h
apt-pkg/orderlist.cc
apt-pkg/packagemanager.cc
apt-pkg/packagemanager.h
apt-pkg/pkgcache.cc
apt-pkg/pkgcache.h
apt-pkg/pkgcachegen.cc
apt-pkg/pkgcachegen.h
apt-pkg/pkgrecords.cc
apt-pkg/pkgrecords.h
apt-pkg/policy.cc
apt-pkg/tagfile.cc
po/apt-all.pot

diff --combined apt-pkg/acquire-item.cc
index 04f0bb943b6c108057a1cf1375340a8cd77ac0a7,0c1aad4859f88b5d4beda75e2c411cc3c43c904d..c42c8af24895c21cf191ef23ceb20dab91a99fac
@@@ -13,9 -13,6 +13,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/acquire-item.h"
- #endif
  #include <apt-pkg/acquire-item.h>
  #include <apt-pkg/configuration.h>
  #include <apt-pkg/sourcelist.h>
@@@ -63,7 -60,6 +60,7 @@@ void pkgAcquire::Item::Failed(string Me
  {
     Status = StatIdle;
     ErrorText = LookupTag(Message,"Message");
 +   UsedMirror =  LookupTag(Message,"UsedMirror");
     if (QueueCounter <= 1)
     {
        /* This indicates that the file is not available right now but might
         Dequeue();
         return;
        }
 -      
 +
        Status = StatError;
        Dequeue();
     }   
 +   
 +   // report mirror failure back to LP if we actually use a mirror
 +   string FailReason = LookupTag(Message, "FailReason");
 +   if(FailReason.size() != 0)
 +      ReportMirrorFailure(FailReason);
 +   else
 +      ReportMirrorFailure(ErrorText);
  }
                                                                        /*}}}*/
  // Acquire::Item::Start - Item has begun to download                  /*{{{*/
@@@ -108,7 -97,6 +105,7 @@@ void pkgAcquire::Item::Done(string Mess
  {
     // We just downloaded something..
     string FileName = LookupTag(Message,"Filename");
 +   UsedMirror =  LookupTag(Message,"UsedMirror");
     if (Complete == false && FileName == DestFile)
     {
        if (Owner->Log != 0)
  
     if (FileSize == 0)
        FileSize= Size;
 -   
     Status = StatDone;
     ErrorText = string();
     Owner->Dequeue(this);
@@@ -139,49 -128,6 +136,49 @@@ void pkgAcquire::Item::Rename(string Fr
  }
                                                                        /*}}}*/
  
 +void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
 +{
 +   // we only act if a mirror was used at all
 +   if(UsedMirror.empty())
 +      return;
 +#if 0
 +   std::cerr << "\nReportMirrorFailure: " 
 +           << UsedMirror
 +           << " Uri: " << DescURI()
 +           << " FailCode: " 
 +           << FailCode << std::endl;
 +#endif
 +   const char *Args[40];
 +   unsigned int i = 0;
 +   string report = _config->Find("Methods::Mirror::ProblemReporting", 
 +                               "/usr/lib/apt/apt-report-mirror-failure");
 +   if(!FileExists(report))
 +      return;
 +   Args[i++] = report.c_str();
 +   Args[i++] = UsedMirror.c_str();
 +   Args[i++] = DescURI().c_str();
 +   Args[i++] = FailCode.c_str();
 +   Args[i++] = NULL;
 +   pid_t pid = ExecFork();
 +   if(pid < 0) 
 +   {
 +      _error->Error("ReportMirrorFailure Fork failed");
 +      return;
 +   }
 +   else if(pid == 0) 
 +   {
 +      execvp(Args[0], (char**)Args);
 +      std::cerr << "Could not exec " << Args[0] << std::endl;
 +      _exit(100);
 +   }
 +   if(!ExecWait(pid, "report-mirror-failure")) 
 +   {
 +      _error->Warning("Couldn't report problem to '%s'",
 +                    _config->Find("Methods::Mirror::ProblemReporting").c_str());
 +   }
 +}
 +
 +
  // AcqIndex::AcqIndex - Constructor                                   /*{{{*/
  // ---------------------------------------------------------------------
  /* The package file is added to the queue and a second class is 
@@@ -227,13 -173,13 +224,13 @@@ string pkgAcqIndex::Custom600Headers(
     struct stat Buf;
     if (stat(Final.c_str(),&Buf) != 0)
        return "\nIndex-File: true";
 -   
     return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
  }
                                                                        /*}}}*/
  
  void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
  {
 +
     // no .bz2 found, retry with .gz
     if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
        Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz"; 
        Complete = false;
        Dequeue();
        return;
 +   } 
 +   
 +   // on decompression failure, remove bad versions in partial/
 +   if(Decompression && Erase) {
 +      string s = _config->FindDir("Dir::State::lists") + "partial/";
 +      s += URItoFileName(RealURI);
 +      unlink(s.c_str());
     }
  
 -   
     Item::Failed(Message,Cnf);
  }
  
@@@ -292,7 -232,6 +289,7 @@@ void pkgAcqIndex::Done(string Message,u
           Status = StatAuthError;
           ErrorText = _("MD5Sum mismatch");
           Rename(DestFile,DestFile + ".FAILED");
 +       ReportMirrorFailure("HashChecksumFailure");
           return;
        }
        // Done, move it into position
     Mode = decompProg;
  }
  
 +// AcqIndexTrans::pkgAcqIndexTrans - Constructor                      /*{{{*/
 +// ---------------------------------------------------------------------
 +/* The Translation file is added to the queue */
 +pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
 +                          string URI,string URIDesc,string ShortDesc) :
 +                      pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, "", "")
 +{
 +}
 +
 +                                                                      /*}}}*/
 +// AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 +{
 +   if (Cnf->LocalOnly == true || 
 +       StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
 +   {      
 +      // Ignore this
 +      Status = StatDone;
 +      Complete = false;
 +      Dequeue();
 +      return;
 +   }
 +   
 +   Item::Failed(Message,Cnf);
 +}
 +                                                                      /*}}}*/
 +
  pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
                             string URI,string URIDesc,string ShortDesc,
                             string MetaIndexURI, string MetaIndexURIDesc,
     DestFile = _config->FindDir("Dir::State::lists") + "partial/";
     DestFile += URItoFileName(URI);
  
 -   // remove any partial downloaded sig-file. it may confuse proxies
 -   // and is too small to warrant a partial download anyway
 +   // remove any partial downloaded sig-file in partial/. 
 +   // it may confuse proxies and is too small to warrant a 
 +   // partial download anyway
     unlink(DestFile.c_str());
  
     // Create the item
@@@ -477,22 -386,17 +474,22 @@@ void pkgAcqMetaSig::Done(string Message
                                                                        /*}}}*/
  void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
  {
 +   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
  
     // if we get a network error we fail gracefully
 -   if(LookupTag(Message,"FailReason") == "Timeout" || 
 -      LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
 -      LookupTag(Message,"FailReason") == "ConnectionRefused") {
 +   if(Status == StatTransientNetworkError)
 +   {
        Item::Failed(Message,Cnf);
 +      // move the sigfile back on network failures (and re-authenticated?)
 +      if(FileExists(DestFile))
 +       Rename(DestFile,Final);
 +
 +      // set the status back to , Item::Failed likes to reset it
 +      Status = pkgAcquire::Item::StatTransientNetworkError;
        return;
     }
  
     // Delete any existing sigfile when the acquire failed
 -   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
     unlink(Final.c_str());
  
     // queue a pkgAcqMetaIndex with no sigfile
@@@ -730,7 -634,7 +727,7 @@@ bool pkgAcqMetaIndex::VerifyVendor(stri
     // check for missing sigs (that where not fatal because otherwise we had
     // bombed earlier)
     string missingkeys;
 -   string msg = _("There are no public key available for the "
 +   string msg = _("There is no public key available for the "
                  "following key IDs:\n");
     pos = Message.find("NO_PUBKEY ");
     if (pos != std::string::npos)
@@@ -815,7 -719,6 +812,7 @@@ void pkgAcqMetaIndex::Failed(string Mes
        }
  
        // gpgv method failed 
 +      ReportMirrorFailure("GPGFailure");
        _error->Warning("GPG error: %s: %s",
                        Desc.Description.c_str(),
                        LookupTag(Message,"Message").c_str());
diff --combined apt-pkg/acquire-item.h
index f659bb459d850e035a35f8e44bde2ff1815492a4,b47e198d8e5b381d8ff69276023dccfb30dac88f..1885f7beb087150394aa4c983c2ddf5e9aa9dd6a
@@@ -9,8 -9,8 +9,8 @@@
     the Owner Acquire class. Derived classes will then call QueueURI to 
     register all the URI's they wish to fetch at the initial moment.   
     
 -   Two item classes are provided to provide functionality for downloading
 -   of Index files and downloading of Packages.
 +   Three item classes are provided to provide functionality for
 +   downloading of Index, Translation and Packages files.
     
     A Archive class is provided for downloading .deb files. It does Md5
     checking and source location as well as a retry algorithm.
@@@ -27,9 -27,6 +27,6 @@@
  #include <apt-pkg/pkgrecords.h>
  #include <apt-pkg/indexrecords.h>
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/acquire-item.h"
- #endif 
  
  // Item to acquire
  class pkgAcquire::Item
@@@ -48,8 -45,7 +45,8 @@@
     public:
  
     // State of the item
 -   enum {StatIdle, StatFetching, StatDone, StatError, StatAuthError} Status;
 +   enum {StatIdle, StatFetching, StatDone, StatError, 
 +       StatAuthError, StatTransientNetworkError} Status;
     string ErrorText;
     unsigned long FileSize;
     unsigned long PartialSize;   
@@@ -57,7 -53,6 +54,7 @@@
     unsigned long ID;
     bool Complete;
     bool Local;
 +   string UsedMirror;
  
     // Number of queues we are inserted into
     unsigned int QueueCounter;
@@@ -80,9 -75,6 +77,9 @@@
     pkgAcquire *GetOwner() {return Owner;};
     virtual bool IsTrusted() {return false;};
     
 +   // report mirror problems
 +   void ReportMirrorFailure(string FailCode);
 +
     Item(pkgAcquire *Owner);
     virtual ~Item();
  };
@@@ -112,16 -104,6 +109,16 @@@ class pkgAcqIndex : public pkgAcquire::
               string ShortDesct, string ExpectedMD5, string compressExt="");
  };
  
 +// Item class for translated package index files
 +class pkgAcqIndexTrans : public pkgAcqIndex
 +{
 +   public:
 +  
 +   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
 +   pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
 +                  string ShortDesct);
 +};
 +
  struct IndexTarget
  {
     string URI;
index 180b52ad7bd689de2215834c85051578bae4d108,3360a8eaea8d773f85d0dfba03df5f553eed587b..dfadf800f5ec5e8fc276756b9a34bbd1a03aab71
@@@ -15,9 -15,6 +15,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/acquire-method.h"
- #endif
  #include <apt-pkg/acquire-method.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/configuration.h>
@@@ -99,11 -96,12 +96,11 @@@ void pkgAcqMethod::Fail(string Err,boo
     }
     
     char S[1024];
 +   char *End = S;
     if (Queue != 0)
     {
 -      snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
 -             "Message: %s %s\n",Queue->Uri.c_str(),Err.c_str(),
 -             FailExtra.c_str());
 -
 +      End += snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
 +                    "Message: %s %s\n",Queue->Uri.c_str(), Err.c_str(), IP.c_str());
        // Dequeue
        FetchItem *Tmp = Queue;
        Queue = Queue->Next;
         QueueBack = Queue;
     }
     else
 -      snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
 -             "Message: %s %s\n",Err.c_str(),
 -             FailExtra.c_str());
 -      
 +   {
 +      End += snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
 +                    "Message: %s\n",Err.c_str());
 +   }
 +   if(FailReason.empty() == false)
 +      End += snprintf(End,sizeof(S)-50 - (End - S),"FailReason: %s\n",FailReason.c_str());
 +   if (UsedMirror.empty() == false)
 +      End += snprintf(End,sizeof(S)-50 - (End - S),"UsedMirror: %s\n",UsedMirror.c_str());
     // Set the transient flag 
     if (Transient == true)
        strcat(S,"Transient-Failure: true\n\n");
@@@ -185,8 -179,6 +182,8 @@@ void pkgAcqMethod::URIDone(FetchResult 
        End += snprintf(End,sizeof(S)-50 - (End - S),"MD5-Hash: %s\n",Res.MD5Sum.c_str());
     if (Res.SHA1Sum.empty() == false)
        End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str());
 +   if (UsedMirror.empty() == false)
 +      End += snprintf(End,sizeof(S)-50 - (End - S),"UsedMirror: %s\n",UsedMirror.c_str());
     if (Res.GPGVOutput.size() > 0)
        End += snprintf(End,sizeof(S)-50 - (End - S),"GPGVOutput:\n");     
     for (vector<string>::iterator I = Res.GPGVOutput.begin();
diff --combined apt-pkg/acquire-method.h
index 20691cc2c3997d2c3419867eeb39ae5d69899aa8,1c0b9f67cf074c825732c20f8826beeee14dc94a..4e72d70942445a3ae433e5dca5f5a4d2dd26fc3a
@@@ -16,9 -16,6 +16,6 @@@
  #include <apt-pkg/configuration.h>
  #include <apt-pkg/strutl.h>
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/acquire-method.h"
- #endif 
  
  class Hashes;
  class pkgAcqMethod
@@@ -54,9 -51,7 +51,9 @@@
     vector<string> Messages;
     FetchItem *Queue;
     FetchItem *QueueBack;
 -   string FailExtra;
 +   string FailReason;
 +   string UsedMirror;
 +   string IP;
     
     // Handlers for messages
     virtual bool Configuration(string Message);
     // Outgoing messages
     void Fail(bool Transient = false);
     inline void Fail(const char *Why, bool Transient = false) {Fail(string(Why),Transient);};
 -   void Fail(string Why, bool Transient = false);
 -   void URIStart(FetchResult &Res);
 -   void URIDone(FetchResult &Res,FetchResult *Alt = 0);
 +   virtual void Fail(string Why, bool Transient = false);
 +   virtual void URIStart(FetchResult &Res);
 +   virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0);
 +
     bool MediaFail(string Required,string Drive);
     virtual void Exit() {};
  
     public:
 -
     enum CnfFlags {SingleInstance = (1<<0),
                    Pipeline = (1<<1), SendConfig = (1<<2),
                    LocalOnly = (1<<3), NeedsCleanup = (1<<4), 
@@@ -82,8 -77,7 +79,8 @@@
     void Status(const char *Format,...);
     
     int Run(bool Single = false);
 -   inline void SetFailExtraMsg(string Msg) {FailExtra = Msg;};
 +   inline void SetFailReason(string Msg) {FailReason = Msg;};
 +   inline void SetIP(string aIP) {IP = aIP;};
     
     pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
     virtual ~pkgAcqMethod() {};
index 8ab67778be5b8322fcbb1967bb74b253144fb494,063aa5ed7e346d627b194393433171917a0f4501..25d40ef542f82a7f8af80c75e6284b6b2c1cf7ff
@@@ -12,9 -12,6 +12,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/acquire-worker.h"
- #endif
  #include <apt-pkg/acquire-worker.h>
  #include <apt-pkg/acquire-item.h>
  #include <apt-pkg/configuration.h>
@@@ -307,13 -304,6 +304,13 @@@ bool pkgAcquire::Worker::RunMessages(
            pkgAcquire::Item *Owner = Itm->Owner;
            pkgAcquire::ItemDesc Desc = *Itm;
            OwnerQ->ItemDone(Itm);
 +
 +          // set some status
 +          if(LookupTag(Message,"FailReason") == "Timeout" || 
 +             LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
 +             LookupTag(Message,"FailReason") == "ConnectionRefused") 
 +             Owner->Status = pkgAcquire::Item::StatTransientNetworkError;
 +
            Owner->Failed(Message,Config);
            ItemDone();
  
diff --combined apt-pkg/acquire.cc
index e1dccf25ab1372b347b004f313403691c7dfbb8a,ed78ec9715c112e4e0a18a12e6a2870be509959a..cbd67055d952a37de89027a85804764869f9a5b8
@@@ -13,9 -13,6 +13,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/acquire.h"
- #endif       
  #include <apt-pkg/acquire.h>
  #include <apt-pkg/acquire-item.h>
  #include <apt-pkg/acquire-worker.h>
@@@ -193,9 -190,9 +190,9 @@@ void pkgAcquire::Enqueue(ItemDesc &Item
     Item.Owner->Status = Item::StatIdle;
     
     // Queue it into the named queue
 -   I->Enqueue(Item);
 -   ToFetch++;
 -         
 +   if(I->Enqueue(Item)) 
 +      ToFetch++;
 +            
     // Some trace stuff
     if (Debug == true)
     {
@@@ -549,17 -546,11 +546,17 @@@ pkgAcquire::Queue::~Queue(
  // Queue::Enqueue - Queue an item to the queue                                /*{{{*/
  // ---------------------------------------------------------------------
  /* */
 -void pkgAcquire::Queue::Enqueue(ItemDesc &Item)
 +bool pkgAcquire::Queue::Enqueue(ItemDesc &Item)
  {
     QItem **I = &Items;
 -   for (; *I != 0; I = &(*I)->Next);
 -   
 +   // move to the end of the queue and check for duplicates here
 +   for (; *I != 0; I = &(*I)->Next)
 +      if (Item.URI == (*I)->URI) 
 +      {
 +       Item.Owner->Status = Item::StatDone;
 +       return false;
 +      }
 +
     // Create a new item
     QItem *Itm = new QItem;
     *Itm = Item;
     Item.Owner->QueueCounter++;   
     if (Items->Next == 0)
        Cycle();
 +   return true;
  }
                                                                        /*}}}*/
  // Queue::Dequeue - Remove an item from the queue                     /*{{{*/
diff --combined apt-pkg/acquire.h
index 1d5daf12e5b56afc61051251eda3d0f4215b5a07,6e836ac49e4020bd1e78365d7c9665c741044a20..5fbc5c8676f5808e55775b1c17fe330f3d83e88a
@@@ -38,9 -38,6 +38,6 @@@
  using std::vector;
  using std::string;
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/acquire.h"
- #endif 
  
  #include <sys/time.h>
  #include <unistd.h>
@@@ -173,7 -170,7 +170,7 @@@ class pkgAcquire::Queu
     public:
     
     // Put an item into this queue
 -   void Enqueue(ItemDesc &Item);
 +   bool Enqueue(ItemDesc &Item);
     bool Dequeue(Item *Owner);
  
     // Find a Queued item
diff --combined apt-pkg/algorithms.cc
index bd814729155e6380a2b61f70bb37a6b3316cb456,3ac98216bfbcb13632f086735949ebcc50de42fb..402d01d69dc24a71c454d3c05c91cb4676c62729
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/algorithms.h"
- #endif 
  #include <apt-pkg/algorithms.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/configuration.h>
 +#include <apt-pkg/version.h>
  #include <apt-pkg/sptr.h>
 +
      
  #include <apti18n.h>
 -    
 +#include <sys/types.h>
  #include <iostream>
                                                                        /*}}}*/
  using namespace std;
@@@ -102,7 -97,6 +99,7 @@@ bool pkgSimulate::Install(PkgIterator i
         DepIterator End;
         D.GlobOr(Start,End);
         if (Start->Type == pkgCache::Dep::Conflicts ||
 +           Start->Type == pkgCache::Dep::DpkgBreaks ||
             Start->Type == pkgCache::Dep::Obsoletes ||
             End->Type == pkgCache::Dep::PreDepends)
           {
@@@ -152,8 -146,6 +149,8 @@@ bool pkgSimulate::Configure(PkgIterato
            cout << " Obsoletes:" << D.TargetPkg().Name();
         else if (D->Type == pkgCache::Dep::Conflicts)
            cout << " Conflicts:" << D.TargetPkg().Name();
 +       else if (D->Type == pkgCache::Dep::DpkgBreaks)
 +          cout << " Breaks:" << D.TargetPkg().Name();
         else
            cout << " Depends:" << D.TargetPkg().Name();
        }           
@@@ -225,8 -217,6 +222,8 @@@ void pkgSimulate::ShortBreaks(
     the necessary calculations to deal with the problems. */
  bool pkgApplyStatus(pkgDepCache &Cache)
  {
 +   pkgDepCache::ActionGroup group(Cache);
 +
     for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
     {
        if (I->VersionList == 0)
          I->InstState == pkgCache::State::HoldReInstReq)
        {
         if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
 -          Cache.MarkKeep(I);
 +          Cache.MarkKeep(I, false, false);
         else
         {
            // Is this right? Will dpkg choke on an upgrade?
            if (Cache[I].CandidateVer != 0 &&
                 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
 -             Cache.MarkInstall(I);
 +             Cache.MarkInstall(I, false, 0, false);
            else
               return _error->Error(_("The package %s needs to be reinstalled, "
                                    "but I can't find an archive for it."),I.Name());
         case pkgCache::State::HalfConfigured:
         if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
             I.State() != pkgCache::PkgIterator::NeedsUnpack)
 -          Cache.MarkKeep(I);
 +          Cache.MarkKeep(I, false, false);
         else
         {
            if (Cache[I].CandidateVer != 0 &&
                 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
 -             Cache.MarkInstall(I);
 +             Cache.MarkInstall(I, true, 0, false);
            else
               Cache.MarkDelete(I);
         }
     on the result. */
  bool pkgFixBroken(pkgDepCache &Cache)
  {
 +   pkgDepCache::ActionGroup group(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);
 +       Cache.MarkInstall(I, true, 0, false);
     
     /* Fix packages that are in a NeedArchive state but don't have a
        downloadable install version */
        if (Cache[I].InstVerIter(Cache).Downloadable() == false)
         continue;
  
 -      Cache.MarkInstall(I,true);      
 +      Cache.MarkInstall(I, true, 0, false);
     }
     
     pkgProblemResolver Fix(&Cache);
   */
  bool pkgDistUpgrade(pkgDepCache &Cache)
  {
 +   pkgDepCache::ActionGroup group(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);
 +       Cache.MarkInstall(I, true, 0, false);
  
     /* 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 & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 -       Cache.MarkInstall(I,true);
 +       Cache.MarkInstall(I, true, 0, false);
     
     /* We do it again over all previously installed packages to force 
        conflict resolution on them all. */
     for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
        if (I->CurrentVer != 0)
 -       Cache.MarkInstall(I,false);
 +       Cache.MarkInstall(I, false, 0, false);
  
     pkgProblemResolver Fix(&Cache);
  
         if (I->SelectedState == pkgCache::State::Hold)
         {
            Fix.Protect(I);
 -          Cache.MarkKeep(I);
 +          Cache.MarkKeep(I, false, false);
         }
        }
     }
     to install packages not marked for install */
  bool pkgAllUpgrade(pkgDepCache &Cache)
  {
 +   pkgDepCache::ActionGroup group(Cache);
 +
     pkgProblemResolver Fix(&Cache);
  
     if (Cache.BrokenCount() != 0)
            continue;
        
        if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
 -       Cache.MarkInstall(I,false);
 +       Cache.MarkInstall(I, false, 0, false);
     }
        
     return Fix.ResolveByKeep();
     the package is restored. */
  bool pkgMinimizeUpgrade(pkgDepCache &Cache)
  {   
 +   pkgDepCache::ActionGroup group(Cache);
 +
     if (Cache.BrokenCount() != 0)
        return false;
     
            continue;
  
         // Keep it and see if that is OK
 -       Cache.MarkKeep(I);
 +       Cache.MarkKeep(I, false, false);
         if (Cache.BrokenCount() != 0)
 -          Cache.MarkInstall(I,false);
 +          Cache.MarkInstall(I, false, 0, false);
         else
         {
            // If keep didnt actually do anything then there was no change..
@@@ -509,10 -491,8 +506,10 @@@ void pkgProblemResolver::MakeScores(
         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)
 +         on the same level. We enhance the score of installed packages 
 +       if those are not obsolete
 +      */
 +      if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
         Score += 1;
     }
  
     installable */
  bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
  {
 +   pkgDepCache::ActionGroup group(Cache);
 +
     if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
        return false;
     if ((Flags[Pkg->ID] & Protected) == Protected)
     Flags[Pkg->ID] &= ~Upgradable;
     
     bool WasKept = Cache[Pkg].Keep();
 -   Cache.MarkInstall(Pkg,false);
 +   Cache.MarkInstall(Pkg, false, 0, false);
  
     // This must be a virtual package or something like that.
     if (Cache[Pkg].InstVerIter(Cache).end() == true)
               /* We let the algorithm deal with conflicts on its next iteration,
                it is much smarter than us */
               if (Start->Type == pkgCache::Dep::Conflicts || 
 +                 Start->Type == pkgCache::Dep::DpkgBreaks || 
                   Start->Type == pkgCache::Dep::Obsoletes)
                   break;
               
     if (Fail == true)
     {
        if (WasKept == true)
 -       Cache.MarkKeep(Pkg);
 +       Cache.MarkKeep(Pkg, false, false);
        else
         Cache.MarkDelete(Pkg);
        return false;
     upgrade packages to advoid problems. */
  bool pkgProblemResolver::Resolve(bool BrokenFix)
  {
 +   pkgDepCache::ActionGroup group(Cache);
 +
     unsigned long Size = Cache.Head().PackageCount;
  
     // Record which packages are marked for install
         {
            if (Cache[I].InstBroken() == true && BrokenFix == true)
            {
 -             Cache.MarkInstall(I,false);
 +             Cache.MarkInstall(I, false, 0, false);
               if (Cache[I].Install() == true)
                  Again = true;
            }
            pkgCache::Version *OldVer = Cache[I].InstallVer;
            Flags[I->ID] &= ReInstateTried;
            
 -          Cache.MarkInstall(I,false);
 +          Cache.MarkInstall(I, false, 0, false);
            if (Cache[I].InstBroken() == true || 
                OldBreaks < Cache.BrokenCount())
            {
               if (OldVer == 0)
                  Cache.MarkDelete(I);
               else
 -                Cache.MarkKeep(I);
 +                Cache.MarkKeep(I, false, false);
            }       
            else
               if (Debug == true)
            continue;
         
         if (Debug == true)
 -          cout << "Investigating " << I.Name() << endl;
 +          clog << "Investigating " << I.Name() << endl;
         
         // Isolate the problem dependency
         PackageKill KillList[100];
                  {
                     if (Debug == true)
                        clog << "  Or group keep for " << I.Name() << endl;
 -                   Cache.MarkKeep(I);
 +                   Cache.MarkKeep(I, false, false);
                     Change = true;
                  }
               }
               OldEnd = LEnd;
            }
            else
 +            {
               Start++;
 +             // We only worry about critical deps.
 +             if (Start.IsCritical() != true)
 +                  continue;
 +            }
  
            // Dep is ok
            if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
            SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
            if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
                Start->Type != pkgCache::Dep::Conflicts &&
 +              Start->Type != pkgCache::Dep::DpkgBreaks &&
                Start->Type != pkgCache::Dep::Obsoletes &&
                Cache[I].NowBroken() == false)
            {          
               }
               
               Change = true;
 -             Cache.MarkKeep(I);                 
 +             Cache.MarkKeep(I, false, false);
               break;
            }
            
               if (Scores[I->ID] <= Scores[Pkg->ID] ||
                   ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
                    End->Type != pkgCache::Dep::Conflicts &&
 +                  End->Type != pkgCache::Dep::DpkgBreaks &&
                    End->Type != pkgCache::Dep::Obsoletes))
               {
                  // Try a little harder to fix protected packages..
                  /* See if a keep will do, unless the package is protected,
                     then installing it will be necessary */
                  bool Installed = Cache[I].Install();
 -                Cache.MarkKeep(I);
 +                Cache.MarkKeep(I, false, false);
                  if (Cache[I].InstBroken() == false)
                  {
                     // Unwind operation will be keep now
                     
                     // Restore
                     if (InOr == true && Installed == true)
 -                      Cache.MarkInstall(I,false);
 +                      Cache.MarkInstall(I, false, 0, false);
                     
                     if (Debug == true)
                        clog << "  Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
                      (Start->Type == pkgCache::Dep::Conflicts ||
                       Start->Type == pkgCache::Dep::Obsoletes))
                     continue;
 -                
 +
 +                if (Start->Type == pkgCache::Dep::DpkgBreaks)
 +                {
 +                   /* Would it help if we upgraded? */
 +                   if (Cache[End] & pkgDepCache::DepGCVer) {
 +                      if (Debug)
 +                         clog << "  Upgrading " << Pkg.Name() << " due to Breaks field in " << I.Name() << endl;
 +                      Cache.MarkInstall(Pkg, false, 0, false);
 +                      continue;
 +                   }
 +                   if (Debug)
 +                      clog << "  Will not break " << Pkg.Name() << " as stated in Breaks field in " << I.Name() <<endl;
 +                   Cache.MarkKeep(I, false, false);
 +                   continue;
 +                }
 +
                  // Skip adding to the kill list if it is protected
                  if ((Flags[Pkg->ID] & Protected) != 0)
                     continue;
            // Hm, nothing can possibly satisify this dep. Nuke it.
            if (VList[0] == 0 && 
                Start->Type != pkgCache::Dep::Conflicts &&
 +              Start->Type != pkgCache::Dep::DpkgBreaks &&
                Start->Type != pkgCache::Dep::Obsoletes &&
                (Flags[I->ID] & Protected) != Protected)
            {
                  
                  // Restore
                  if (InOr == true && Installed == true)
 -                   Cache.MarkInstall(I,false);
 +                   Cache.MarkInstall(I, false, 0, false);
                  
                  if (Debug == true)
                     clog << "  Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
               {
                  if (Debug == true)
                     clog << "  Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
 -                Cache.MarkKeep(J->Pkg);
 +                Cache.MarkKeep(J->Pkg, false, false);
               }
  
               if (Counter > 1)
        return _error->Error(_("Unable to correct problems, you have held broken packages."));
     }
     
 +   // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
 +   // I didn't managed 
 +   pkgCache::PkgIterator I = Cache.PkgBegin();
 +   for (;I.end() != true; I++) {
 +      if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
 +       if(_config->FindI("Debug::pkgAutoRemove",false)) {
 +          std::clog << "Resolve installed new pkg: " << I.Name() 
 +                    << " (now marking it as auto)" << std::endl;
 +       }
 +       Cache[I].Flags |= pkgCache::Flag::Auto;
 +      }
 +   }
 +
 +
     return true;
  }
                                                                        /*}}}*/
     system was non-broken previously. */
  bool pkgProblemResolver::ResolveByKeep()
  {
 +   pkgDepCache::ActionGroup group(Cache);
 +
     unsigned long Size = Cache.Head().PackageCount;
  
     if (Debug == true)      
        {
         if (Debug == true)
            clog << "Keeping package " << I.Name() << endl;
 -       Cache.MarkKeep(I);
 +       Cache.MarkKeep(I, false, false);
         if (Cache[I].InstBroken() == false)
         {
            K = PList - 1;
               {
                  if (Debug == true)
                     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
 -                Cache.MarkKeep(Pkg);
 +                Cache.MarkKeep(Pkg, false, false);
               }
               
               if (Cache[I].InstBroken() == false)
  /* This is used to make sure protected packages are installed */
  void pkgProblemResolver::InstallProtect()
  {
 +   pkgDepCache::ActionGroup group(Cache);
 +
     for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
     {
        if ((Flags[I->ID] & Protected) == Protected)
        {
         if ((Flags[I->ID] & ToRemove) == ToRemove)
            Cache.MarkDelete(I);
 -       else
 -          Cache.MarkInstall(I,false);
 +       else 
 +       {
 +          // preserver the information if the package was auto
 +          // or manual installed
 +          bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
 +          Cache.MarkInstall(I, false, 0, !autoInst);
 +       }
        }
     }   
  }
@@@ -1300,4 -1229,3 +1297,4 @@@ void pkgPrioSortList(pkgCache &Cache,pk
     qsort(List,Count,sizeof(*List),PrioComp);
  }
                                                                        /*}}}*/
 +
diff --combined apt-pkg/cacheiterators.h
index d5a9c7b0db89712e79255783d808a92f9e00aade,c412eaa978035c322dbfc71789ea9e598fb161f2..08eafca0f44db8e722299e68307b9f887e0b6dd9
@@@ -31,9 -31,6 +31,6 @@@
  #ifndef PKGLIB_CACHEITERATORS_H
  #define PKGLIB_CACHEITERATORS_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/cacheiterators.h"
- #endif 
  
  // Package Iterator
  class pkgCache::PkgIterator
@@@ -99,7 -96,7 +96,7 @@@ class pkgCache::VerIterato
  {
     Version *Ver;
     pkgCache *Owner;
 -   
 +
     void _dummy();
     
     public:
     inline const char *Section() const {return Ver->Section == 0?0:Owner->StrP + Ver->Section;};
     inline const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;};
     inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);};
 +   inline DescIterator DescriptionList() const;
 +   DescIterator TranslatedDescription() const;
     inline DepIterator DependsList() const;
     inline PrvIterator ProvidesList() const;
     inline VerFileIterator FileList() const;
     };
  };
  
 +// Description Iterator
 +class pkgCache::DescIterator
 +{
 +   Description *Desc;
 +   pkgCache *Owner;
 +   
 +   void _dummy();
 +   
 +   public:
 +
 +   // Iteration
 +   void operator ++(int) {if (Desc != Owner->DescP) Desc = Owner->DescP + Desc->NextDesc;};
 +   inline void operator ++() {operator ++(0);};
 +   inline bool end() const {return Desc == Owner->DescP?true:false;};
 +   inline void operator =(const DescIterator &B) {Desc = B.Desc; Owner = B.Owner;};
 +   
 +   // Comparison
 +   inline bool operator ==(const DescIterator &B) const {return Desc == B.Desc;};
 +   inline bool operator !=(const DescIterator &B) const {return Desc != B.Desc;};
 +   int CompareDesc(const DescIterator &B) const;
 +   
 +   // Accessors
 +   inline Description *operator ->() {return Desc;};
 +   inline Description const *operator ->() const {return Desc;};
 +   inline Description &operator *() {return *Desc;};
 +   inline Description const &operator *() const {return *Desc;};
 +   inline operator Description *() {return Desc == Owner->DescP?0:Desc;};
 +   inline operator Description const *() const {return Desc == Owner->DescP?0:Desc;};
 +   inline pkgCache *Cache() {return Owner;};
 +      
 +   inline const char *LanguageCode() const {return Owner->StrP + Desc->language_code;};
 +   inline const char *md5() const {return Owner->StrP + Desc->md5sum;};
 +   inline DescFileIterator FileList() const;
 +   inline unsigned long Index() const {return Desc - Owner->DescP;};
 +
 +   inline DescIterator() : Desc(0), Owner(0) {};   
 +   inline DescIterator(pkgCache &Owner,Description *Trg = 0) : Desc(Trg), 
 +              Owner(&Owner) 
 +   { 
 +      if (Desc == 0)
 +       Desc = Owner.DescP;
 +   };
 +};
 +
  // Dependency iterator
  class pkgCache::DepIterator
  {
@@@ -384,38 -335,6 +381,38 @@@ class pkgCache::VerFileIterato
     inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {};
  };
  
 +// Description File 
 +class pkgCache::DescFileIterator
 +{
 +   pkgCache *Owner;
 +   DescFile *FileP;
 +
 +   public:
 +
 +   // Iteration
 +   void operator ++(int) {if (FileP != Owner->DescFileP) FileP = Owner->DescFileP + FileP->NextFile;};
 +   inline void operator ++() {operator ++(0);};
 +   inline bool end() const {return FileP == Owner->DescFileP?true:false;};
 +
 +   // Comparison
 +   inline bool operator ==(const DescFileIterator &B) const {return FileP == B.FileP;};
 +   inline bool operator !=(const DescFileIterator &B) const {return FileP != B.FileP;};
 +                         
 +   // Accessors
 +   inline DescFile *operator ->() {return FileP;};
 +   inline DescFile const *operator ->() const {return FileP;};
 +   inline DescFile const &operator *() const {return *FileP;};
 +   inline operator DescFile *() {return FileP == Owner->DescFileP?0:FileP;};
 +   inline operator DescFile const *() const {return FileP == Owner->DescFileP?0:FileP;};
 +   inline pkgCache *Cache() {return Owner;};
 +  
 +   inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
 +   inline unsigned long Index() const {return FileP - Owner->DescFileP;};
 +      
 +   inline DescFileIterator() : Owner(0), FileP(0) {};
 +   inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Owner(&Owner), FileP(Trg) {};
 +};
 +
  // Inlined Begin functions cant be in the class because of order problems
  inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const
         {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);};
@@@ -425,15 -344,11 +422,15 @@@ inline pkgCache::DepIterator pkgCache::
         {return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);};
  inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const
         {return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);};
 +inline pkgCache::DescIterator pkgCache::VerIterator::DescriptionList() const
 +       {return DescIterator(*Owner,Owner->DescP + Ver->DescriptionList);};
  inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const
         {return PrvIterator(*Owner,Owner->ProvideP + Ver->ProvidesList,Ver);};
  inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const
         {return DepIterator(*Owner,Owner->DepP + Ver->DependsList,Ver);};
  inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const
         {return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);};
 +inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const
 +       {return DescFileIterator(*Owner,Owner->DescFileP + Desc->FileList);};
  
  #endif
diff --combined apt-pkg/cdrom.cc
index aefe9c9e976c33582d01a3df32eaa162513a616f,9b0568d8f04c179e1904cee5c03ba0d323a25730..55f342d9f552615fbf324b7b2cc85a05ae560896
@@@ -1,9 -1,6 +1,6 @@@
  /*
   */
  
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/cdrom.h"
- #endif
  #include<apt-pkg/init.h>
  #include<apt-pkg/error.h>
  #include<apt-pkg/cdromutl.h>
@@@ -30,16 -27,12 +27,16 @@@ using namespace std
     search that short circuits when it his a package file in the dir.
     This speeds it up greatly as the majority of the size is in the
     binary-* sub dirs. */
 -bool pkgCdrom::FindPackages(string CD,vector<string> &List,
 -                          vector<string> &SList, vector<string> &SigList,
 +bool pkgCdrom::FindPackages(string CD,
 +                          vector<string> &List,
 +                          vector<string> &SList, 
 +                          vector<string> &SigList,
 +                          vector<string> &TransList,
                            string &InfoDir, pkgCdromStatus *log,
                            unsigned int Depth)
  {
     static ino_t Inodes[9];
 +   DIR *D;
  
     // if we have a look we "pulse" now
     if(log)
        if (_config->FindB("APT::CDROM::Thorough",false) == false)
         return true;
     }
 +
 +   // see if we find translatin indexes
 +   if (stat("i18n",&Buf) == 0)
 +   {
 +      D = opendir("i18n");
 +      for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
 +      {
 +       if(strstr(Dir->d_name,"Translation") != NULL) 
 +       {
 +          if (_config->FindB("Debug::aptcdrom",false) == true)
 +             std::clog << "found translations: " << Dir->d_name << "\n";
 +          string file = Dir->d_name;
 +          if(file.substr(file.size()-3,file.size()) == ".gz")
 +             file = file.substr(0,file.size()-3);
 +          TransList.push_back(CD+"i18n/"+ file);
 +       }
 +      }
 +      closedir(D);
 +   }
 +
     
 -   DIR *D = opendir(".");
 +   D = opendir(".");
     if (D == 0)
        return _error->Errno("opendir","Unable to read %s",CD.c_str());
     
        Inodes[Depth] = Buf.st_ino;
  
        // Descend
 -      if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
 +      if (FindPackages(CD + Dir->d_name,List,SList,SigList,TransList,InfoDir,log,Depth+1) == false)
         break;
  
        if (chdir(CD.c_str()) != 0)
@@@ -636,10 -609,9 +633,10 @@@ bool pkgCdrom::Add(pkgCdromStatus *log
     vector<string> List;
     vector<string> SourceList;
     vector<string> SigList;
 +   vector<string> TransList;
     string StartDir = SafeGetCWD();
     string InfoDir;
 -   if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
 +   if (FindPackages(CDROM,List,SourceList, SigList,TransList,InfoDir,log) == false)
     {
        log->Update("\n");
        return false;
     DropRepeats(List,"Packages");
     DropRepeats(SourceList,"Sources");
     DropRepeats(SigList,"Release.gpg");
 +   DropRepeats(TransList,"");
     if(log) {
        msg.str("");
 -      ioprintf(msg, _("Found %i package indexes, %i source indexes and "
 -                    "%i signatures\n"), 
 -             List.size(), SourceList.size(), SigList.size());
 +      ioprintf(msg, _("Found %i package indexes, %i source indexes, "
 +                    "%i translation indexes and %i signatures\n"), 
 +             List.size(), SourceList.size(), TransList.size(),
 +             SigList.size());
        log->Update(msg.str(), STEP_SCAN);
     }
  
     if (List.size() == 0 && SourceList.size() == 0) 
     {
 -      UnmountCdrom(CDROM);
 +      if (_config->FindB("APT::CDROM::NoMount",false) == false) 
 +       UnmountCdrom(CDROM);
        return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
     }
  
        {
         if(!log) 
           {
 -          UnmountCdrom(CDROM);
 +          if (_config->FindB("APT::CDROM::NoMount",false) == false) 
 +             UnmountCdrom(CDROM);
            return _error->Error("No disc name found and no way to ask for it");
         }
  
     // Copy the package files to the state directory
     PackageCopy Copy;
     SourceCopy SrcCopy;
 +   TranslationsCopy TransCopy;
     if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
 -       SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
 +       SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false ||
 +       TransCopy.CopyTranslations(CDROM,Name,TransList, log) == false)
        return false;
  
     // reduce the List so that it takes less space in sources.list
        string::size_type Space = (*I).find(' ');
        if (Space == string::npos)
        {
 -       UnmountCdrom(CDROM);
 +       if (_config->FindB("APT::CDROM::NoMount",false) == false) 
 +          UnmountCdrom(CDROM);
         return _error->Error("Internal error");
        }
  
        string::size_type Space = (*I).find(' ');
        if (Space == string::npos)
        {
 -       UnmountCdrom(CDROM);
 +       if (_config->FindB("APT::CDROM::NoMount",false) == false) 
 +          UnmountCdrom(CDROM);
         return _error->Error("Internal error");
        }
  
diff --combined apt-pkg/cdrom.h
index e18aaff3e6ddd32ef9e7cb0b51efbbf2619ef211,b8b208c30d7a6a32c4a3410cbb9e9ae42dee2384..68d61c0989b6193014eb969479f900f1cfc46690
@@@ -5,9 -5,6 +5,6 @@@
  #include<string>
  #include<vector>
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/cdrom.h"
- #endif
  
  using namespace std;
  
@@@ -50,11 -47,8 +47,11 @@@ class pkgCdro
     };
  
  
 -   bool FindPackages(string CD,vector<string> &List,
 -                   vector<string> &SList, vector<string> &SigList,
 +   bool FindPackages(string CD,
 +                   vector<string> &List,
 +                   vector<string> &SList, 
 +                   vector<string> &SigList,
 +                   vector<string> &TransList,
                     string &InfoDir, pkgCdromStatus *log,
                     unsigned int Depth = 0);
     bool DropBinaryArch(vector<string> &List);
index db140ec02d256e13c52aaf147c7380ddb33a1b18,1264982a89e98a238ec534ee97099f2216bc025a..f24bb8c704fdb85ee1d2447b74a0b3b8998a3fdd
@@@ -8,19 -8,14 +8,15 @@@
     ##################################################################### */
                                                                        /*}}}*/
  #ifndef PKGLIB_CDROMUTL_H
 -#define PKGLIB_ACQUIRE_METHOD_H
 +#define PKGLIB_CDROMUTL_H
  
  #include <string>
  
  using std::string;
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/cdromutl.h"
- #endif 
  bool MountCdrom(string Path);
  bool UnmountCdrom(string Path);
  bool IdentCdrom(string CD,string &Res,unsigned int Version = 2);
 +bool IsMounted(string &Path);
  
  #endif
index e3db9a45aa1720c1d791caca362139142d474461,ffd1191e52c4e608950d2c84f20b46fd49909eac..6ce6e950a788a90d603ac693ac215113c8b43cb6
@@@ -8,9 -8,6 +8,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/progress.h"
- #endif 
  #include <apt-pkg/progress.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/configuration.h>
@@@ -115,8 -112,6 +112,8 @@@ bool OpProgress::CheckChange(float Inte
     
     if ((int)LastPercent == (int)Percent)
        return false;
 +
 +   LastPercent = Percent;
     
     if (Interval == 0)
        return false;
     if (Diff < Interval)
        return false;
     LastTime = Now;   
 -   LastPercent = Percent;
     return true;
  }
                                                                        /*}}}*/
diff --combined apt-pkg/contrib/sha256.h
index 70b3ae2ad0178794de5ca2423e8fa9d16234ed7f,01b638d56979c9bf4052ea5d1efb5414378af282..c490bfa4df30cf348766f617470774013a9cdec3
  #ifndef APTPKG_SHA256_H
  #define APTPKG_SHA256_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/sha256.h"
- #endif 
  #include <string>
  #include <algorithm>
 -#include <stdint.h>
  
  using std::string;
  using std::min;
index 37d263794b42b9c2049096068e2b3b99124371bd,aa37a099a55a4f3fa1d5b22028d3313d11020c43..ae5409aa1f7f87b246d1b7f38a0d69e1988254c2
     ##################################################################### */
                                                                        /*}}}*/
  // Includes                                                           /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/strutl.h"
- #endif
  #include <apt-pkg/strutl.h>
  #include <apt-pkg/fileutl.h>
  #include <apt-pkg/error.h>
  #include <regex.h>
  #include <errno.h>
  #include <stdarg.h>
 +#include <iconv.h>
  
  #include "config.h"
  
  using namespace std;
                                                                        /*}}}*/
  
 +// UTF8ToCodeset - Convert some UTF-8 string for some codeset         /*{{{*/
 +// ---------------------------------------------------------------------
 +/* This is handy to use before display some information for enduser  */
 +bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
 +{
 +  iconv_t cd;
 +  const char *inbuf;
 +  char *inptr, *outbuf, *outptr;
 +  size_t insize, outsize;
 +  
 +  cd = iconv_open(codeset, "UTF-8");
 +  if (cd == (iconv_t)(-1)) {
 +     // Something went wrong
 +     if (errno == EINVAL)
 +      _error->Error("conversion from 'UTF-8' to '%s' not available",
 +               codeset);
 +     else
 +      perror("iconv_open");
 +     
 +     // Clean the destination string
 +     *dest = "";
 +     
 +     return false;
 +  }
 +
 +  insize = outsize = orig.size();
 +  inbuf = orig.data();
 +  inptr = (char *)inbuf;
 +  outbuf = new char[insize+1];
 +  outptr = outbuf;
 +
 +  iconv(cd, &inptr, &insize, &outptr, &outsize);
 +  *outptr = '\0';
 +
 +  *dest = outbuf;
 +  delete[] outbuf;
 +  
 +  iconv_close(cd);
 +
 +  return true;
 +}
 +                                                                      /*}}}*/
  // strstrip - Remove white space from the front and back of a string  /*{{{*/
  // ---------------------------------------------------------------------
  /* This is handy to use when parsing a file. It also removes \n's left 
diff --combined apt-pkg/contrib/strutl.h
index 254087267d74476de6b19d9f8696ae8f250d1eea,b8553ab587f8eafc2144a044af7772689a04677e..ae1244ecd10b6e0efcce45814bfaefc28280773c
@@@ -16,9 -16,7 +16,7 @@@
  #ifndef STRUTL_H
  #define STRUTL_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/strutl.h"
- #endif 
  
  #include <stdlib.h>
  #include <string>
@@@ -38,8 -36,7 +36,8 @@@ using std::ostream
  #define APT_FORMAT2
  #define APT_FORMAT3
  #endif    
 -    
 +
 +bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest);
  char *_strstrip(char *String);
  char *_strtabexpand(char *String,size_t Len);
  bool ParseQuoteWord(const char *&String,string &Res);
index 9f435bba55dc4df5da75afa718e6f9149aeab6a3,2d52f7c45837c5f1ec88bda895341b310be970ae..ed76338032fb46659825b2e0da838cc2dfd90b29
@@@ -9,10 -9,6 +9,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/debindexfile.h"
- #endif
  #include <apt-pkg/debindexfile.h>
  #include <apt-pkg/debsrcrecords.h>
  #include <apt-pkg/deblistparser.h>
@@@ -305,7 -301,7 +301,7 @@@ pkgCache::PkgFileIterator debPackagesIn
     pkgCache::PkgFileIterator File = Cache.FileBegin();
     for (; File.end() == false; File++)
     {
 -      if (FileName != File.FileName())
 +       if (File.FileName() == NULL || FileName != File.FileName())
         continue;
        
        struct stat St;
  }
                                                                        /*}}}*/
  
 +// TranslationsIndex::debTranslationsIndex - Contructor                       /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) : 
 +                  pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section)
 +{
 +}
 +                                                                      /*}}}*/
 +// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +inline string debTranslationsIndex::IndexFile(const char *Type) const
 +{
 +   return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
 +}
 +string debTranslationsIndex::IndexURI(const char *Type) const
 +{
 +   string Res;
 +   if (Dist[Dist.size() - 1] == '/')
 +   {
 +      if (Dist != "/")
 +       Res = URI + Dist;
 +      else 
 +       Res = URI;
 +   }
 +   else
 +      Res = URI + "dists/" + Dist + '/' + Section +
 +      "/i18n/Translation-";
 +   
 +   Res += Type;
 +   return Res;
 +}
 +                                                                      /*}}}*/
 +// TranslationsIndex::GetIndexes - Fetch the index files              /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
 +{
 +   if (TranslationsAvailable()) {
 +     string TranslationFile = "Translation-" + LanguageCode();
 +     new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()),
 +                        Info(TranslationFile.c_str()),
 +                        TranslationFile);
 +   }
 +
 +   return true;
 +}
 +                                                                      /*}}}*/
 +// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
 +// ---------------------------------------------------------------------
 +/* This should help the user find the index in the sources.list and
 +   in the filesystem for problem solving */
 +string debTranslationsIndex::Describe(bool Short) const
 +{   
 +   char S[300];
 +   if (Short == true)
 +      snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
 +   else
 +      snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
 +             IndexFile(LanguageCode().c_str()).c_str());
 +   return S;
 +}
 +                                                                      /*}}}*/
 +// TranslationsIndex::Info - One liner describing the index URI               /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +string debTranslationsIndex::Info(const char *Type) const 
 +{
 +   string Info = ::URI::SiteOnly(URI) + ' ';
 +   if (Dist[Dist.size() - 1] == '/')
 +   {
 +      if (Dist != "/")
 +       Info += Dist;
 +   }
 +   else
 +      Info += Dist + '/' + Section;   
 +   Info += " ";
 +   Info += Type;
 +   return Info;
 +}
 +                                                                      /*}}}*/
 +bool debTranslationsIndex::HasPackages() const
 +{
 +   if(!TranslationsAvailable())
 +      return false;
 +   
 +   return FileExists(IndexFile(LanguageCode().c_str()));
 +}
 +
 +// TranslationsIndex::Exists - Check if the index is available                /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +bool debTranslationsIndex::Exists() const
 +{
 +   return FileExists(IndexFile(LanguageCode().c_str()));
 +}
 +                                                                      /*}}}*/
 +// TranslationsIndex::Size - Return the size of the index             /*{{{*/
 +// ---------------------------------------------------------------------
 +/* This is really only used for progress reporting. */
 +unsigned long debTranslationsIndex::Size() const
 +{
 +   struct stat S;
 +   if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0)
 +      return 0;
 +   return S.st_size;
 +}
 +                                                                      /*}}}*/
 +// TranslationsIndex::Merge - Load the index file into a cache                /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
 +{
 +   // Check the translation file, if in use
 +   string TranslationFile = IndexFile(LanguageCode().c_str());
 +   if (TranslationsAvailable() && FileExists(TranslationFile))
 +   {
 +     FileFd Trans(TranslationFile,FileFd::ReadOnly);
 +     debListParser TransParser(&Trans);
 +     if (_error->PendingError() == true)
 +       return false;
 +     
 +     Prog.SubProgress(0, Info(TranslationFile.c_str()));
 +     if (Gen.SelectFile(TranslationFile,string(),*this) == false)
 +       return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
 +
 +     // Store the IMS information
 +     pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
 +     struct stat TransSt;
 +     if (fstat(Trans.Fd(),&TransSt) != 0)
 +       return _error->Errno("fstat","Failed to stat");
 +     TransFile->Size = TransSt.st_size;
 +     TransFile->mtime = TransSt.st_mtime;
 +   
 +     if (Gen.MergeList(TransParser) == false)
 +       return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
 +   }
 +
 +   return true;
 +}
 +                                                                      /*}}}*/
 +// TranslationsIndex::FindInCache - Find this index                           /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
 +{
 +   string FileName = IndexFile(LanguageCode().c_str());
 +   
 +   pkgCache::PkgFileIterator File = Cache.FileBegin();
 +   for (; File.end() == false; File++)
 +   {
 +      if (FileName != File.FileName())
 +       continue;
 +
 +      struct stat St;
 +      if (stat(File.FileName(),&St) != 0)
 +       return pkgCache::PkgFileIterator(Cache);
 +      if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
 +       return pkgCache::PkgFileIterator(Cache);
 +      return File;
 +   }   
 +   return File;
 +}
 +                                                                      /*}}}*/
  // StatusIndex::debStatusIndex - Constructor                          /*{{{*/
  // ---------------------------------------------------------------------
  /* */
@@@ -580,11 -412,6 +576,11 @@@ class debIFTypePkg : public pkgIndexFil
     };
     debIFTypePkg() {Label = "Debian Package Index";};
  };
 +class debIFTypeTrans : public debIFTypePkg
 +{
 +   public:
 +   debIFTypeTrans() {Label = "Debian Translation Index";};
 +};
  class debIFTypeStatus : public pkgIndexFile::Type
  {
     public:
  };
  static debIFTypeSrc _apt_Src;
  static debIFTypePkg _apt_Pkg;
 +static debIFTypeTrans _apt_Trans;
  static debIFTypeStatus _apt_Status;
  
  const pkgIndexFile::Type *debSourcesIndex::GetType() const
@@@ -608,10 -434,6 +604,10 @@@ const pkgIndexFile::Type *debPackagesIn
  {
     return &_apt_Pkg;
  }
 +const pkgIndexFile::Type *debTranslationsIndex::GetType() const
 +{
 +   return &_apt_Trans;
 +}
  const pkgIndexFile::Type *debStatusIndex::GetType() const
  {
     return &_apt_Status;
index 57005222fdbc761ea619813f9795e889a79902e4,2bc9635677fa64807cbf125be753173df5534f13..b0012c96b94fcf85f9793123f49506eb656de249
@@@ -16,9 -16,7 +16,7 @@@
  #ifndef PKGLIB_DEBINDEXFILE_H
  #define PKGLIB_DEBINDEXFILE_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/debindexfile.h"
- #endif
  
  #include <apt-pkg/indexfile.h>
  
@@@ -74,36 -72,6 +72,36 @@@ class debPackagesIndex : public pkgInde
     debPackagesIndex(string URI,string Dist,string Section,bool Trusted);
  };
  
 +class debTranslationsIndex : public pkgIndexFile
 +{
 +   string URI;
 +   string Dist;
 +   string Section;
 +   
 +   string Info(const char *Type) const;
 +   string IndexFile(const char *Type) const;
 +   string IndexURI(const char *Type) const;
 +
 +   inline string TranslationFile() const {return "Translation-" + LanguageCode();};
 +
 +   public:
 +   
 +   virtual const Type *GetType() const;
 +
 +   // Interface for acquire
 +   virtual string Describe(bool Short) const;   
 +   virtual bool GetIndexes(pkgAcquire *Owner) const;
 +   
 +   // Interface for the Cache Generator
 +   virtual bool Exists() const;
 +   virtual bool HasPackages() const;
 +   virtual unsigned long Size() const;
 +   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
 +   virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 +
 +   debTranslationsIndex(string URI,string Dist,string Section);
 +};
 +
  class debSourcesIndex : public pkgIndexFile
  {
     string URI;
index 8cf31b3260446d385c44ef35ecfd66da08b6e186,6830f9e835a772a1d6b9c0536d1032b395b275d7..73b2dda498c53b59462a90b923fb7a5b80cefae0
@@@ -1,9 -1,5 +1,5 @@@
  // ijones, walters
  
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/debmetaindex.h"
- #endif
  #include <apt-pkg/debmetaindex.h>
  #include <apt-pkg/debindexfile.h>
  #include <apt-pkg/strutl.h>
@@@ -157,16 -153,6 +153,16 @@@ bool debReleaseIndex::GetIndexes(pkgAcq
                     ComputeIndexTargets(),
                     new indexRecords (Dist));
  
 +   // Queue the translations
 +   for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
 +      I != SectionEntries.end(); I++) {
 +
 +      if((*I)->IsSrc)
 +       continue;
 +      debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section);
 +      i.GetIndexes(Owner);
 +   }
 +
     return true;
  }
  
@@@ -191,16 -177,11 +187,16 @@@ vector <pkgIndexFile *> *debReleaseInde
  
     Indexes = new vector <pkgIndexFile*>;
     for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
 -      I != SectionEntries.end(); I++)
 +      I != SectionEntries.end(); I++) {
        if ((*I)->IsSrc)
           Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
        else 
 +      {
           Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
 +       Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section));
 +      }
 +   }
 +
     return Indexes;
  }
  
index 5eb2d67bb9d63408170eb9ff04122dc1810249cb,6ecbd15d62695e1b1b174fc972dee5206340d9af..5421b3db706d0670b13f4071fd6b81bdaf2f8cab
@@@ -8,13 -8,8 +8,10 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/debrecords.h"
- #endif
  #include <apt-pkg/debrecords.h>
 +#include <apt-pkg/strutl.h>
  #include <apt-pkg/error.h>
 +#include <langinfo.h>
                                                                        /*}}}*/
  
  // RecordParser::debRecordParser - Constructor                                /*{{{*/
@@@ -32,10 -27,6 +29,10 @@@ debRecordParser::debRecordParser(strin
  bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
  {
     return Tags.Jump(Section,Ver->Offset);
 +}
 +bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
 +{
 +   return Tags.Jump(Section,Desc->Offset);
  }
                                                                        /*}}}*/
  // RecordParser::FileName - Return the archive filename on the site   /*{{{*/
@@@ -67,7 -58,7 +64,7 @@@ string debRecordParser::MD5Hash(
  /* */
  string debRecordParser::SHA1Hash()
  {
 -   return Section.FindS("SHA1Sum");
 +   return Section.FindS("SHA1");
  }
                                                                        /*}}}*/
  // RecordParser::Maintainer - Return the maintainer email             /*{{{*/
@@@ -83,7 -74,7 +80,7 @@@ string debRecordParser::Maintainer(
  /* */
  string debRecordParser::ShortDesc()
  {
 -   string Res = Section.FindS("Description");
 +   string Res = LongDesc();
     string::size_type Pos = Res.find('\n');
     if (Pos == string::npos)
        return Res;
  /* */
  string debRecordParser::LongDesc()
  {
 -   return Section.FindS("Description");
 +  string orig, dest;
 +  char *codeset = nl_langinfo(CODESET);
 +
 +  if (!Section.FindS("Description").empty())
 +     orig = Section.FindS("Description").c_str();
 +  else 
 +     orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str();
 +
 +  if (strcmp(codeset,"UTF-8") != 0) {
 +     UTF8ToCodeset(codeset, orig, &dest);
 +     orig = dest;
 +   }    
 +  
 +   return orig;
  }
                                                                        /*}}}*/
  // RecordParser::SourcePkg - Return the source package name if any    /*{{{*/
diff --combined apt-pkg/deb/debrecords.h
index 24e5aab88761f231ab24622e4d64bae619286137,3f1956164fb6c1fe5d0360a2c21a51f0126a5d67..fdf8d762b9a0010188f39807ae87ffc2d47228a9
  #ifndef PKGLIB_DEBRECORDS_H
  #define PKGLIB_DEBRECORDS_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/debrecords.h"
- #endif 
  #include <apt-pkg/pkgrecords.h>
 +#include <apt-pkg/indexfile.h>
  #include <apt-pkg/tagfile.h>
  
  class debRecordParser : public pkgRecords::Parser
@@@ -31,7 -26,6 +27,7 @@@
     protected:
     
     virtual bool Jump(pkgCache::VerFileIterator const &Ver);
 +   virtual bool Jump(pkgCache::DescFileIterator const &Desc);
     
     public:
  
index 9e87ee5dadc8293aa9b3caf9b7ce5afdff966165,21d7392a0da6c726095b0ad03f16d392c22128b6..7338de15dd483643d9ab1b0b380d2b7278507953
@@@ -9,17 -9,11 +9,13 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/debsrcrecords.h"
- #endif 
  #include <apt-pkg/deblistparser.h>
  #include <apt-pkg/debsrcrecords.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/strutl.h>
  #include <apt-pkg/configuration.h>
 +
 +using std::max;
                                                                        /*}}}*/
  
  // SrcRecordParser::Binaries - Return the binaries field              /*{{{*/
@@@ -36,19 -30,31 +32,19 @@@ const char **debSrcRecordParser::Binari
     if (Bins.empty() == true || Bins.length() >= 102400)
        return 0;
     
 -   // Workaround for #236688.  Only allocate a new buffer if the field
 -   // is large, to avoid a performance penalty
 -   char *BigBuf = NULL;
 -   char *Buf;
 -   if (Bins.length() > sizeof(Buffer))
 -   {
 -      BigBuf = new char[Bins.length()];
 -      Buf = BigBuf;
 -   }
 -   else
 +   if (Bins.length() >= BufSize)
     {
 -      Buf = Buffer;
 +      delete [] Buffer;
 +      // allocate new size based on buffer (but never smaller than 4000)
 +      BufSize = max((unsigned long)4000, max((unsigned long)Bins.length()+1,2*BufSize));
 +      Buffer = new char[BufSize];
     }
  
 -   strcpy(Buf,Bins.c_str());
 -   if (TokSplitString(',',Buf,StaticBinList,
 +   strcpy(Buffer,Bins.c_str());
 +   if (TokSplitString(',',Buffer,StaticBinList,
                      sizeof(StaticBinList)/sizeof(StaticBinList[0])) == false)
 -   {
 -      if (BigBuf != NULL)
 -         delete BigBuf;
        return 0;
 -   }
  
 -   if (BigBuf != NULL)
 -      delete BigBuf;
     return (const char **)StaticBinList;
  }
                                                                        /*}}}*/
index f4e2cb46c9c6adb78473f612311313394cbfb5d5,51e0638127593df7d96dab6e20535c14aa76d17d..55fdcb667830b395b16eb0ca3951f8627cc8d435
@@@ -11,9 -11,6 +11,6 @@@
  #ifndef PKGLIB_DEBSRCRECORDS_H
  #define PKGLIB_DEBSRCRECORDS_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/debsrcrecords.h"
- #endif 
  
  #include <apt-pkg/srcrecords.h>
  #include <apt-pkg/tagfile.h>
@@@ -24,10 -21,9 +21,10 @@@ class debSrcRecordParser : public pkgSr
     FileFd Fd;
     pkgTagFile Tags;
     pkgTagSection Sect;
 -   char Buffer[10000];
     char *StaticBinList[400];
     unsigned long iOffset;
 +   char *Buffer;
 +   unsigned long BufSize;
     
     public:
  
     };
     virtual bool Files(vector<pkgSrcRecords::File> &F);
  
 -   debSrcRecordParser(string File,pkgIndexFile const *Index) :
 -                   Parser(Index),      
 -                   Fd(File,FileFd::ReadOnly),
 -                   Tags(&Fd,102400) {};
 +   debSrcRecordParser(string File,pkgIndexFile const *Index) 
 +      : Parser(Index), Fd(File,FileFd::ReadOnly), Tags(&Fd,102400), 
 +        Buffer(0), BufSize(0) {}
  };
  
  #endif
diff --combined apt-pkg/deb/dpkgpm.cc
index 5c069458e483d51600cd9969188a7a17ca813d3e,905ac93c4f1c654db5c82a82c5edbe23de7af5cb..4b4bba696387aaa85928bdbe9d06a3c4015f48f2
@@@ -8,14 -8,10 +8,11 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Includes                                                           /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/dpkgpm.h"
- #endif
  #include <apt-pkg/dpkgpm.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/configuration.h>
  #include <apt-pkg/depcache.h>
 +#include <apt-pkg/pkgrecords.h>
  #include <apt-pkg/strutl.h>
  
  #include <unistd.h>
@@@ -38,8 -34,7 +35,8 @@@ using namespace std
  // DPkgPM::pkgDPkgPM - Constructor                                    /*{{{*/
  // ---------------------------------------------------------------------
  /* */
 -pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache)
 +pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) 
 +   : pkgPackageManager(Cache), pkgFailures(0)
  {
  }
                                                                        /*}}}*/
@@@ -476,8 -471,6 +473,8 @@@ bool pkgDPkgPM::Go(int OutStatusFd
         case Item::Install:
         Args[n++] = "--unpack";
         Size += strlen(Args[n-1]);
 +       Args[n++] = "--auto-deconfigure";
 +       Size += strlen(Args[n-1]);
         break;
        }
        
            
         */
         char* list[5];
 -       if(!TokSplitString(':', line, list, sizeof(list)/sizeof(list[0])))
 -          // FIXME: dpkg sends multiline error messages sometimes (see
 -          //        #374195 for a example. we should support this by
 -          //        either patching dpkg to not send multiline over the
 -          //        statusfd or by rewriting the code here to deal with
 -          //        it. for now we just ignore it and not crash
 -          continue;
 +       //        dpkg sends multiline error messages sometimes (see
 +       //        #374195 for a example. we should support this by
 +       //        either patching dpkg to not send multiline over the
 +       //        statusfd or by rewriting the code here to deal with
 +       //        it. for now we just ignore it and not crash
 +       TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
         char *pkg = list[1];
         char *action = _strstrip(list[2]);
 +       if( pkg == NULL || action == NULL) 
 +       {
 +          if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 +             std::clog << "ignoring line: not enough ':'" << std::endl;
 +          // reset the line buffer
 +          line[0]=0;
 +          continue;
 +       }
  
         if(strncmp(action,"error",strlen("error")) == 0)
         {
            line[0]=0;
            if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
               std::clog << "send: '" << status.str() << "'" << endl;
 +          pkgFailures++;
 +          WriteApportReport(list[1], list[3]);
            continue;
         }
         if(strncmp(action,"conffile",strlen("conffile")) == 0)
        // Check for an error code.
        if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
        {
 -       RunScripts("DPkg::Post-Invoke");
 -       if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
 -          return _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
 -
 -       if (WIFEXITED(Status) != 0)
 -          return _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
 +       // if it was set to "keep-dpkg-runing" then we won't return
 +       // here but keep the loop going and just report it as a error
 +       // for later
 +       bool stopOnError = _config->FindB("Dpkg::StopOnError",true);
         
 -       return _error->Error("Sub-process %s exited unexpectedly",Args[0]);
 +       if(stopOnError)
 +          RunScripts("DPkg::Post-Invoke");
 +
 +       if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV) 
 +          _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
 +       else if (WIFEXITED(Status) != 0)
 +          _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
 +       else 
 +          _error->Error("Sub-process %s exited unexpectedly",Args[0]);
 +
 +       if(stopOnError)
 +          return false;
        }      
     }
  
@@@ -750,94 -725,3 +747,94 @@@ void pkgDPkgPM::Reset(
     List.erase(List.begin(),List.end());
  }
                                                                        /*}}}*/
 +// pkgDpkgPM::WriteApportReport - write out error report pkg failure  /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) 
 +{
 +   string pkgname, reportfile, srcpkgname, pkgver, arch;
 +   string::size_type pos;
 +   FILE *report;
 +
 +   if (_config->FindB("Dpkg::ApportFailureReport",true) == false)
 +      return;
 +
 +   // only report the first error if we are in StopOnError=false mode
 +   // to prevent bogus reports
 +   if((_config->FindB("Dpkg::StopOnError",true) == false) && pkgFailures > 1)
 +      return;
 +
 +   // get the pkgname and reportfile
 +   pkgname = flNotDir(pkgpath);
 +   pos = pkgname.rfind('_');
 +   if(pos != string::npos)
 +      pkgname = string(pkgname, 0, pos);
 +
 +   // find the package versin and source package name
 +   pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname);
 +   if (Pkg.end() == true)
 +      return;
 +   pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
 +   pkgver = Ver.VerStr();
 +   if (Ver.end() == true)
 +      return;
 +   pkgRecords Recs(Cache);
 +   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
 +   srcpkgname = Parse.SourcePkg();
 +   if(srcpkgname.empty())
 +      srcpkgname = pkgname;
 +
 +   // if the file exists already, we check:
 +   // - if it was reported already (touched by apport). 
 +   //   If not, we do nothing, otherwise
 +   //    we overwrite it. This is the same behaviour as apport
 +   // - if we have a report with the same pkgversion already
 +   //   then we skip it
 +   reportfile = flCombine("/var/crash",pkgname+".0.crash");
 +   if(FileExists(reportfile))
 +   {
 +      struct stat buf;
 +      char strbuf[255];
 +
 +      // check atime/mtime
 +      stat(reportfile.c_str(), &buf);
 +      if(buf.st_mtime > buf.st_atime)
 +       return;
 +
 +      // check if the existing report is the same version
 +      report = fopen(reportfile.c_str(),"r");
 +      while(fgets(strbuf, sizeof(strbuf), report) != NULL)
 +      {
 +       if(strstr(strbuf,"Package:") == strbuf)
 +       {
 +          char pkgname[255], version[255];
 +          if(sscanf(strbuf, "Package: %s %s", pkgname, version) == 2)
 +             if(strcmp(pkgver.c_str(), version) == 0)
 +             {
 +                fclose(report);
 +                return;
 +             }
 +       }
 +      }
 +      fclose(report);
 +   }
 +
 +   // now write the report
 +   arch = _config->Find("APT::Architecture");
 +   report = fopen(reportfile.c_str(),"w");
 +   if(report == NULL)
 +      return;
 +   if(_config->FindB("DPkgPM::InitialReportOnly",false) == true)
 +      chmod(reportfile.c_str(), 0);
 +   else
 +      chmod(reportfile.c_str(), 0600);
 +   fprintf(report, "ProblemType: Package\n");
 +   fprintf(report, "Architecture: %s\n", arch.c_str());
 +   time_t now = time(NULL);
 +   fprintf(report, "Date: %s" , ctime(&now));
 +   fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str());
 +   fprintf(report, "SourcePackage: %s\n", srcpkgname.c_str());
 +   fprintf(report, "ErrorMessage:\n %s\n", errormsg);
 +   fclose(report);
 +}
 +                                                                      /*}}}*/
diff --combined apt-pkg/deb/dpkgpm.h
index 1a1fdc1912c94d5355868c2f4250b8361999b701,45eb6b15b0d8898b2f56f00c5bc31f0d63552605..a413f3a902a54f535f36b1864fe5a94a8ad97325
  #ifndef PKGLIB_DPKGPM_H
  #define PKGLIB_DPKGPM_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/dpkgpm.h"
- #endif
  #include <apt-pkg/packagemanager.h>
  #include <vector>
  #include <stdio.h>
@@@ -23,7 -19,6 +19,7 @@@ using std::vector
  class pkgDPkgPM : public pkgPackageManager
  {
     protected:
 +   int pkgFailures;
  
     // used for progress reporting
     struct DpkgState 
     bool RunScripts(const char *Cnf);
     bool RunScriptsWithPkgs(const char *Cnf);
     bool SendV2Pkgs(FILE *F);
 -   
 +
 +   // apport integration
 +   void WriteApportReport(const char *pkgpath, const char *errormsg);
 +
     // The Actuall installation implementation
     virtual bool Install(PkgIterator Pkg,string File);
     virtual bool Configure(PkgIterator Pkg);
diff --combined apt-pkg/depcache.cc
index 27e0ff73fc96532edb56e2a050bac9f911961dc4,70bc9f086b2d5d409a412d765c432eff32e2e2aa..9f0fa143d3e033b90ea5d7ef468922c63713022c
@@@ -8,62 -8,21 +8,59 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/depcache.h"
- #endif
  #include <apt-pkg/depcache.h>
  #include <apt-pkg/version.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/sptr.h>
  #include <apt-pkg/algorithms.h>
 +
 +#include <apt-pkg/fileutl.h>
  #include <apt-pkg/configuration.h>
 +#include <apt-pkg/pkgsystem.h>
 +#include <apt-pkg/tagfile.h>
 +
 +#include <iostream>
 +#include <sstream>    
 +#include <set>
 +
 +#include <sys/stat.h>
  
  #include <apti18n.h>    
 -                                                                      /*}}}*/
 +
 +pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
 +  cache(cache), released(false)
 +{
 +  ++cache.group_level;
 +}
 +
 +void pkgDepCache::ActionGroup::release()
 +{
 +  if(!released)
 +    {
 +      if(cache.group_level == 0)
 +      std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
 +      else
 +      {
 +        --cache.group_level;
 +
 +        if(cache.group_level == 0)
 +          cache.MarkAndSweep();
 +      }
 +
 +      released = false;
 +    }
 +}
 +
 +pkgDepCache::ActionGroup::~ActionGroup()
 +{
 +  release();
 +}
  
  // DepCache::pkgDepCache - Constructors                                       /*{{{*/
  // ---------------------------------------------------------------------
  /* */
  pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
 -                Cache(pCache), PkgState(0), DepState(0)
 +  group_level(0), Cache(pCache), PkgState(0), DepState(0)
  {
     delLocalPolicy = 0;
     LocalPolicy = Plcy;
@@@ -86,10 -45,6 +83,10 @@@ pkgDepCache::~pkgDepCache(
  /* This allocats the extension buffers and initializes them. */
  bool pkgDepCache::Init(OpProgress *Prog)
  {
 +   // Suppress mark updates during this operation (just in case) and
 +   // run a mark operation when Init terminates.
 +   ActionGroup actions(*this);
 +
     delete [] PkgState;
     delete [] DepState;
     PkgState = new StateCache[Head().PackageCount];
        // 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();
  
     if(Prog != 0)
        Prog->Done();
 -   
 +
     return true;
  } 
                                                                        /*}}}*/
  
 +bool pkgDepCache::readStateFile(OpProgress *Prog)
 +{
 +   FileFd state_file;
 +   string state = _config->FindDir("Dir::State") + "extended_states";
 +   if(FileExists(state)) {
 +      state_file.Open(state, FileFd::ReadOnly);
 +      int file_size = state_file.Size();
 +      if(Prog != NULL)
 +       Prog->OverallProgress(0, file_size, 1, 
 +                             _("Reading state information"));
 +
 +      pkgTagFile tagfile(&state_file);
 +      pkgTagSection section;
 +      int amt=0;
 +      while(tagfile.Step(section)) {
 +       string pkgname = section.FindS("Package");
 +       pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
 +       // Silently ignore unknown packages and packages with no actual
 +       // version.
 +       if(!pkg.end() && !pkg.VersionList().end()) {
 +          short reason = section.FindI("Auto-Installed", 0);
 +          if(reason > 0)
 +             PkgState[pkg->ID].Flags  |= Flag::Auto;
 +          if(_config->FindB("Debug::pkgAutoRemove",false))
 +             std::cout << "Auto-Installed : " << pkgname << std::endl;
 +          amt+=section.size();
 +          if(Prog != NULL)
 +             Prog->OverallProgress(amt, file_size, 1, 
 +                                   _("Reading state information"));
 +       }
 +       if(Prog != NULL)
 +          Prog->OverallProgress(file_size, file_size, 1, 
 +                                _("Reading state information"));
 +      }
 +   }
 +
 +   return true;
 +}
 +
 +bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
 +{
 +   if(_config->FindB("Debug::pkgAutoRemove",false))
 +      std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 +
 +   FileFd StateFile;
 +   string state = _config->FindDir("Dir::State") + "extended_states";
 +
 +   // if it does not exist, create a empty one
 +   if(!FileExists(state)) 
 +   {
 +      StateFile.Open(state, FileFd::WriteEmpty);
 +      StateFile.Close();
 +   }
 +
 +   // open it
 +   if(!StateFile.Open(state, FileFd::ReadOnly))
 +      return _error->Error(_("Failed to open StateFile %s"),
 +                         state.c_str());
 +
 +   FILE *OutFile;
 +   string outfile = state + ".tmp";
 +   if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
 +      return _error->Error(_("Failed to write temporary StateFile %s"),
 +                         outfile.c_str());
 +
 +   // first merge with the existing sections
 +   pkgTagFile tagfile(&StateFile);
 +   pkgTagSection section;
 +   std::set<string> pkgs_seen;
 +   const char *nullreorderlist[] = {0};
 +   while(tagfile.Step(section)) {
 +       string pkgname = section.FindS("Package");
 +       // Silently ignore unknown packages and packages with no actual
 +       // version.
 +       pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
 +       if(pkg.end() || pkg.VersionList().end()) 
 +          continue;
 +       bool oldAuto = section.FindI("Auto-Installed");
 +       bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
 +       if(_config->FindB("Debug::pkgAutoRemove",false))
 +          std::clog << "Update exisiting AutoInstall info: " 
 +                    << pkg.Name() << std::endl;
 +       TFRewriteData rewrite[2];
 +       rewrite[0].Tag = "Auto-Installed";
 +       rewrite[0].Rewrite = newAuto ? "1" : "0";
 +       rewrite[0].NewTag = 0;
 +       rewrite[1].Tag = 0;
 +       TFRewrite(OutFile, section, nullreorderlist, rewrite);
 +       fprintf(OutFile,"\n");
 +       pkgs_seen.insert(pkgname);
 +   }
 +   
 +   // then write the ones we have not seen yet
 +   std::ostringstream ostr;
 +   for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
 +      if(PkgState[pkg->ID].Flags & Flag::Auto) {
 +       if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
 +          if(_config->FindB("Debug::pkgAutoRemove",false))
 +             std::clog << "Skipping already written " << pkg.Name() << std::endl;
 +          continue;
 +       }
 +       // skip not installed ones if requested
 +       if(InstalledOnly && pkg->CurrentVer == 0)
 +          continue;
 +       if(_config->FindB("Debug::pkgAutoRemove",false))
 +          std::clog << "Writing new AutoInstall: " 
 +                    << pkg.Name() << std::endl;
 +       ostr.str(string(""));
 +       ostr << "Package: " << pkg.Name() 
 +            << "\nAuto-Installed: 1\n\n";
 +       fprintf(OutFile,ostr.str().c_str());
 +       fprintf(OutFile,"\n");
 +      }
 +   }
 +   fclose(OutFile);
 +
 +   // move the outfile over the real file and set permissions
 +   rename(outfile.c_str(), state.c_str());
 +   chmod(state.c_str(), 0644);
 +
 +   return true;
 +}
 +
  // DepCache::CheckDep - Checks a single dependency                    /*{{{*/
  // ---------------------------------------------------------------------
  /* This first checks the dependency against the main target package and
@@@ -279,7 -111,7 +276,7 @@@ bool pkgDepCache::CheckDep(DepIterator 
        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 && Dep->Type != Dep::Obsoletes))
 +       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
     {
        PkgIterator Pkg = Dep.TargetPkg();
        // Check the base package
     {
        /* 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)
 +      if (P.OwnerPkg() == Pkg &&
 +        (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
         continue;
        
        // Check if the provides is a hit
@@@ -406,11 -237,9 +403,11 @@@ void pkgDepCache::AddStates(const PkgIt
  {
     StateCache &State = PkgState[Pkg->ID];
     
 -   // The Package is broken
 +   // The Package is broken (either minimal dep or policy dep)
     if ((State.DepState & DepInstMin) != DepInstMin)
        iBrokenCount += Add;
 +   if ((State.DepState & DepInstPolicy) != DepInstPolicy)
 +      iPolicyBrokenCount += Add;
     
     // Bad state
     if (Pkg.State() != PkgIterator::NeedsNothing)
@@@ -464,9 -293,7 +461,9 @@@ void pkgDepCache::BuildGroupOrs(VerIter
  
        /* Invert for Conflicts. We have to do this twice to get the
           right sense for a conflicts group */
 -      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 +      if (D->Type == Dep::Conflicts ||
 +        D->Type == Dep::DpkgBreaks ||
 +        D->Type == Dep::Obsoletes)
         State = ~State;
        
        // Add to the group if we are within an or..
         Group = 0;
        
        // Invert for Conflicts
 -      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 +      if (D->Type == Dep::Conflicts ||
 +        D->Type == Dep::DpkgBreaks ||
 +        D->Type == Dep::Obsoletes)
         State = ~State;
     }   
  }
@@@ -612,9 -437,7 +609,9 @@@ void pkgDepCache::Update(OpProgress *Pr
               Group = 0;
  
            // Invert for Conflicts
 -          if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 +          if (D->Type == Dep::Conflicts ||
 +              D->Type == Dep::DpkgBreaks ||
 +              D->Type == Dep::Obsoletes)
               State = ~State;
         }       
        }
  
     if (Prog != 0)      
        Prog->Progress(Done);
 +
 +   readStateFile(Prog);
  }
                                                                        /*}}}*/
  // 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. */
 +   It is mainly meant to scan reverse dependencies. */
  void pkgDepCache::Update(DepIterator D)
  {
     // Update the reverse deps
        State = DependencyState(D);
      
        // Invert for Conflicts
 -      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 +      if (D->Type == Dep::Conflicts ||
 +        D->Type == Dep::DpkgBreaks ||
 +        D->Type == Dep::Obsoletes)
         State = ~State;
  
        RemoveStates(D.ParentPkg());
@@@ -688,7 -507,7 +685,7 @@@ void pkgDepCache::Update(PkgIterator co
  // DepCache::MarkKeep - Put the package in the keep state             /*{{{*/
  // ---------------------------------------------------------------------
  /* */
 -void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
 +void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
  {
     // Simplifies other routines.
     if (Pkg.end() == true)
         Pkg.CurrentVer().Downloadable() == false)
        return;
     
 +   /** \todo Can this be moved later in the method? */
 +   ActionGroup group(*this);
 +
     /* We changed the soft state all the time so the UI is a bit nicer
        to use */
     StateCache &P = PkgState[Pkg->ID];
     // We dont even try to keep virtual packages..
     if (Pkg->VersionList == 0)
        return;
 -   
 -   P.Flags &= ~Flag::Auto;
 +
 +#if 0 // reseting the autoflag here means we lose the 
 +      // auto-mark information if a user selects a package for removal
 +      // but changes  his mind then and sets it for keep again
 +      // - this makes sense as default when all Garbage dependencies
 +      //   are automatically marked for removal (as aptitude does).
 +      //   setting a package for keep then makes it no longer autoinstalled
 +      //   for all other use-case this action is rather suprising
 +   if(FromUser && !P.Marked)
 +     P.Flags &= ~Flag::Auto;
 +#endif
 +
     RemoveSizes(Pkg);
     RemoveStates(Pkg);
  
@@@ -755,8 -561,6 +752,8 @@@ void pkgDepCache::MarkDelete(PkgIterato
     if (Pkg.end() == true)
        return;
  
 +   ActionGroup group(*this);
 +
     // Check that it is not already marked for delete
     StateCache &P = PkgState[Pkg->ID];
     P.iFlags &= ~(AutoKept | Purge);
     else
        P.Mode = ModeDelete;
     P.InstallVer = 0;
 -   P.Flags &= Flag::Auto;
  
     AddStates(Pkg);   
     Update(Pkg);
  // ---------------------------------------------------------------------
  /* */
  void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 -                            unsigned long Depth)
 +                            unsigned long Depth, bool FromUser,
 +                            bool ForceImportantDeps)
  {
     if (Depth > 100)
        return;
     if (Pkg.end() == true)
        return;
     
 +   ActionGroup group(*this);
 +
     /* 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 ||
 +   if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && 
 +       (P.Mode == ModeInstall ||
        P.CandidateVer == (Version *)Pkg.CurrentVer()))
     {
        if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
 -       MarkKeep(Pkg);
 +       MarkKeep(Pkg, false, FromUser);
        return;
     }
  
     // See if there is even any possible instalation candidate
     if (P.CandidateVer == 0)
        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 */
     
     P.Mode = ModeInstall;
     P.InstallVer = P.CandidateVer;
 -   P.Flags &= ~Flag::Auto;
 +
 +   if(FromUser)
 +     {
 +       // Set it to manual if it's a new install or cancelling the
 +       // removal of a garbage package.
 +       if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
 +       P.Flags &= ~Flag::Auto;
 +     }
 +   else
 +     {
 +       // Set it to auto if this is a new install.
 +       if(P.Status == 2)
 +       P.Flags |= Flag::Auto;
 +     }
     if (P.CandidateVer == (Version *)Pkg.CurrentVer())
        P.Mode = ModeKeep;
         
  
        /* 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 */
 +       it will be installed. Otherwise we only check for important
 +         deps that have changed from the installed version
 +      */
        if (IsImportantDep(Start) == false)
         continue;
 -      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
 +      
 +      /* check if any ImportantDep() (but not Critial) where added
 +       * since we installed the package
 +       */
 +      bool isNewImportantDep = false;
 +      if(!ForceImportantDeps && !Start.IsCritical())
 +      {
 +       bool found=false;
 +       VerIterator instVer = Pkg.CurrentVer();
 +       if(!instVer.end())
 +       {
 +          for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
 +          {
 +             //FIXME: deal better with or-groups(?)
 +             DepIterator LocalStart = D;
 +             
 +             if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
 +                found=true;
 +          }
 +          // this is a new dep if it was not found to be already
 +          // a important dep of the installed pacakge
 +          isNewImportantDep = !found;
 +       }
 +      }
 +      if(isNewImportantDep)
 +       if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 +          std::clog << "new important dependency: " 
 +                    << Start.TargetPkg().Name() << std::endl;
 +
 +      // skip important deps if the package is already installed
 +      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
 +        && !isNewImportantDep && !ForceImportantDeps)
         continue;
        
        /* If we are in an or group locate the first or that can 
        /* This bit is for processing the possibilty of an install/upgrade
           fixing the problem */
        SPtrArray<Version *> List = Start.AllTargets();
 -      if ((DepState[Start->ID] & DepCVer) == DepCVer)
 +      if (Start->Type != Dep::DpkgBreaks &&
 +        (DepState[Start->ID] & DepCVer) == DepCVer)
        {
         // Right, find the best version to install..
         Version **Cur = List;
            }
         }
         
 -       if (InstPkg.end() == false)
 +       if (InstPkg.end() == false) 
         {
            if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
               std::clog << "Installing " << InstPkg.Name() 
                         << " as dep of " << Pkg.Name() 
                         << std::endl;
 -          MarkInstall(InstPkg,true,Depth + 1);
  
 -          // Set the autoflag, after MarkInstall because MarkInstall unsets it
 -          if (P->CurrentVer == 0)
 -             PkgState[InstPkg->ID].Flags |= Flag::Auto;
 +          // now check if we should consider it a automatic dependency or not
 +          string sec = _config->Find("APT::Never-MarkAuto-Section","");
 +          if(Pkg.Section() && (string(Pkg.Section()) ==  sec))
 +          {
 +             if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 +                std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
 +             MarkInstall(InstPkg,true,Depth + 1, true, ForceImportantDeps);
 +          }
 +          else 
 +          {
 +             // mark automatic dependency
 +             MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
 +             // Set the autoflag, after MarkInstall because MarkInstall unsets it
 +             if (P->CurrentVer == 0)
 +                PkgState[InstPkg->ID].Flags |= Flag::Auto;
 +          }
         }
 -       
         continue;
        }
 -      
 +
        /* For conflicts we just de-install the package and mark as auto,
 -         Conflicts may not have or groups */
 -      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
 +         Conflicts may not have or groups.  For dpkg's Breaks we try to
 +         upgrade the package. */
 +      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
 +        Start->Type == Dep::DpkgBreaks)
        {
         for (Version **I = List; *I != 0; I++)
         {
            VerIterator Ver(*this,*I);
            PkgIterator Pkg = Ver.ParentPkg();
 -      
 -          MarkDelete(Pkg);
 -          PkgState[Pkg->ID].Flags |= Flag::Auto;
 +
 +          if (Start->Type != Dep::DpkgBreaks)
 +             MarkDelete(Pkg);
 +          else
 +             if (PkgState[Pkg->ID].CandidateVer != *I)
 +                MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
         }
         continue;
        }      
  /* */
  void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
  {
 +   ActionGroup group(*this);
 +
     RemoveSizes(Pkg);
     RemoveStates(Pkg);
     
  /* */
  void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
  {
 +   ActionGroup group(*this);
 +
     pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
     StateCache &P = PkgState[Pkg->ID];
 -   
 +
     RemoveSizes(Pkg);
     RemoveStates(Pkg);
  
     Update(Pkg);
     AddSizes(Pkg);
  }
 +
 +void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
 +{
 +  StateCache &state = PkgState[Pkg->ID];
 +
 +  ActionGroup group(*this);
 +
 +  if(Auto)
 +    state.Flags |= Flag::Auto;
 +  else
 +    state.Flags &= ~Flag::Auto;
 +}
                                                                        /*}}}*/
  // StateCache::Update - Compute the various static display things     /*{{{*/
  // ---------------------------------------------------------------------
@@@ -1137,251 -861,11 +1134,251 @@@ pkgCache::VerIterator pkgDepCache::Poli
     return Last;
  }
                                                                        /*}}}*/
 +                                                                      /*}}}*/
 +
 +pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
 +  : constructedSuccessfully(false)
 +{
 +  Configuration::Item const *Opts;
 +  Opts = _config->Tree("APT::NeverAutoRemove");
 +  if (Opts != 0 && Opts->Child != 0)
 +    {
 +      Opts = Opts->Child;
 +      for (; Opts != 0; Opts = Opts->Next)
 +      {
 +        if (Opts->Value.empty() == true)
 +          continue;
 +
 +        regex_t *p = new regex_t;
 +        if(regcomp(p,Opts->Value.c_str(),
 +                   REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
 +          {
 +            regfree(p);
 +            delete p;
 +            _error->Error("Regex compilation error for APT::NeverAutoRemove");
 +            return;
 +          }
 +
 +        rootSetRegexp.push_back(p);
 +      }
 +    }
 +
 +  constructedSuccessfully = true;
 +}
 +
 +pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
 +{
 +  for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
 +    {
 +      regfree(rootSetRegexp[i]);
 +      delete rootSetRegexp[i];
 +    }
 +}
 +
 +
 +bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
 +{
 +   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
 +      if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
 +       return true;
 +
 +   return false;
 +}
 +
 +pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
 +{
 +  DefaultRootSetFunc *f = new DefaultRootSetFunc;
 +  if(f->wasConstructedSuccessfully())
 +    return f;
 +  else
 +    {
 +      delete f;
 +      return NULL;
 +    }
 +}
 +
 +bool pkgDepCache::MarkFollowsRecommends()
 +{
 +  return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
 +}
 +
 +bool pkgDepCache::MarkFollowsSuggests()
 +{
 +  return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
 +}
 +
 +// the main mark algorithm
 +bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 +{
 +   bool follow_recommends;
 +   bool follow_suggests;
 +
 +   // init the states
 +   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
 +   {
 +      PkgState[p->ID].Marked  = false;
 +      PkgState[p->ID].Garbage = false;
 +
 +      // debug output
 +      if(_config->FindB("Debug::pkgAutoRemove",false) 
 +       && PkgState[p->ID].Flags & Flag::Auto)
 +       std::clog << "AutoDep: " << p.Name() << std::endl;
 +   }
 +
 +   // init vars
 +   follow_recommends = MarkFollowsRecommends();
 +   follow_suggests   = MarkFollowsSuggests();
 +
 +
 +
 +   // do the mark part, this is the core bit of the algorithm
 +   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
 +   {
 +      if(!(PkgState[p->ID].Flags & Flag::Auto) ||
 +        (p->Flags & Flag::Essential) ||
 +        userFunc.InRootSet(p))
 +          
 +      {
 +       // the package is installed (and set to keep)
 +       if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
 +          MarkPackage(p, p.CurrentVer(),
 +                      follow_recommends, follow_suggests);
 +       // the package is to be installed 
 +       else if(PkgState[p->ID].Install())
 +          MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
 +                      follow_recommends, follow_suggests);
 +      }
 +   }
 +
 +   return true;
 +}
 +
 +// mark a single package in Mark-and-Sweep
 +void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 +                            const pkgCache::VerIterator &ver,
 +                            bool follow_recommends,
 +                            bool follow_suggests)
 +{
 +   pkgDepCache::StateCache &state = PkgState[pkg->ID];
 +   VerIterator candver            = state.CandidateVerIter(*this);
 +   VerIterator instver            = state.InstVerIter(*this);
 +
 +#if 0
 +   // If a package was garbage-collected but is now being marked, we
 +   // should re-select it 
 +   // For cases when a pkg is set to upgrade and this trigger the
 +   // removal of a no-longer used dependency.  if the pkg is set to
 +   // keep again later it will result in broken deps
 +   if(state.Delete() && state.RemoveReason = Unused) 
 +   {
 +      if(ver==candver)
 +       mark_install(pkg, false, false, NULL);
 +      else if(ver==pkg.CurrentVer())
 +       MarkKeep(pkg, false, false);
 +      
 +      instver=state.InstVerIter(*this);
 +   }
 +#endif
 +
 +   // Ignore versions other than the InstVer, and ignore packages
 +   // that are already going to be removed or just left uninstalled.
 +   if(!(ver == instver && !instver.end()))
 +      return;
 +
 +   // if we are marked already we are done
 +   if(state.Marked)
 +      return;
 +
 +   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
 +   state.Marked=true;
 +
 +   if(!ver.end())
 +   {
 +     for(DepIterator d = ver.DependsList(); !d.end(); ++d)
 +     {
 +      if(d->Type == Dep::Depends ||
 +         d->Type == Dep::PreDepends ||
 +         (follow_recommends &&
 +          d->Type == Dep::Recommends) ||
 +         (follow_suggests &&
 +          d->Type == Dep::Suggests))
 +        {
 +         // Try all versions of this package.
 +         for(VerIterator V = d.TargetPkg().VersionList(); 
 +             !V.end(); ++V)
 +         {
 +            if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
 +            {
 +               MarkPackage(V.ParentPkg(), V, 
 +                           follow_recommends, follow_suggests);
 +            }
 +         }
 +         // Now try virtual packages
 +         for(PrvIterator prv=d.TargetPkg().ProvidesList(); 
 +             !prv.end(); ++prv)
 +         {
 +            if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
 +                                     d.TargetVer()))
 +            {
 +               MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
 +                           follow_recommends, follow_suggests);
 +            }
 +         }
 +      }
 +     }
 +   }
 +}
 +
 +bool pkgDepCache::Sweep()
 +{
 +   // do the sweep
 +   for(PkgIterator p=PkgBegin(); !p.end(); ++p)
 +  {
 +     StateCache &state=PkgState[p->ID];
 +
 +     // skip required packages
 +     if (!p.CurrentVer().end() && 
 +       (p.CurrentVer()->Priority == pkgCache::State::Required))
 +      continue;
 +
 +     // if it is not marked and it is installed, it's garbage 
 +     if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
 +     {
 +      state.Garbage=true;
 +      if(_config->FindB("Debug::pkgAutoRemove",false))
 +         std::cout << "Garbage: " << p.Name() << std::endl;
 +     }
 +  }   
 +
 +   return true;
 +}
 +
  // Policy::IsImportantDep - True if the dependency is important               /*{{{*/
  // ---------------------------------------------------------------------
  /* */
  bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
  {
 -   return Dep.IsCritical();
 +   if(Dep.IsCritical())
 +      return true;
 +   else if(Dep->Type == pkgCache::Dep::Recommends) 
 +   {
 +      if ( _config->FindB("APT::Install-Recommends", false))
 +       return true;
 +      // we suport a special mode to only install-recommends for certain
 +      // sections
 +      // FIXME: this is a meant as a temporarly solution until the 
 +      //        recommends are cleaned up
 +      string s = _config->Find("APT::Install-Recommends-Section","");
 +      if(s.size() > 0) 
 +      {
 +       const char *sec = Dep.ParentVer().Section();
 +       if (sec && strcmp(sec, s.c_str()) == 0)
 +          return true;
 +      }
 +   }
 +   else if(Dep->Type == pkgCache::Dep::Suggests)
 +     return _config->FindB("APT::Install-Suggests", false);
 +
 +   return false;
  }
                                                                        /*}}}*/
diff --combined apt-pkg/depcache.h
index 8f759d345a1f49121267b73fe295d5fe753c64f5,929fe93c981ec199c05f328bfed6c1195ae78941..84fed7f3732fc455bdab2c298680928cfc7c1f17
@@@ -1,4 -1,4 +1,4 @@@
 -// -*- mode: cpp; mode: fold -*-
 +// -*- mode: c++; mode: fold -*-
  // Description                                                                /*{{{*/
  // $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
  /* ######################################################################
  #ifndef PKGLIB_DEPCACHE_H
  #define PKGLIB_DEPCACHE_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/depcache.h"
- #endif
  
  #include <apt-pkg/pkgcache.h>
  #include <apt-pkg/progress.h>
  
 +#include <regex.h>
 +
 +#include <vector>
 +
  class pkgDepCache : protected pkgCache::Namespace
  {
     public:
 +
 +   /** \brief An arbitrary predicate on packages. */
 +   class InRootSetFunc
 +   {
 +   public:
 +     virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;};
 +     virtual ~InRootSetFunc() {};
 +   };
 +
 +   private:
 +   /** \brief Mark a single package and all its unmarked important
 +    *  dependencies during mark-and-sweep.
 +    *
 +    *  Recursively invokes itself to mark all dependencies of the
 +    *  package.
 +    *
 +    *  \param pkg The package to mark.
 +    *
 +    *  \param ver The version of the package that is to be marked.
 +    *
 +    *  \param follow_recommends If \b true, recommendations of the
 +    *  package will be recursively marked.
 +    *
 +    *  \param follow_suggests If \b true, suggestions of the package
 +    *  will be recursively marked.
 +    */
 +   void MarkPackage(const pkgCache::PkgIterator &pkg,
 +                  const pkgCache::VerIterator &ver,
 +                  bool follow_recommends,
 +                  bool follow_suggests);
 +
 +   /** \brief Update the Marked field of all packages.
 +    *
 +    *  Each package's StateCache::Marked field will be set to \b true
 +    *  if and only if it can be reached from the root set.  By
 +    *  default, the root set consists of the set of manually installed
 +    *  or essential packages, but it can be extended using the
 +    *  parameter #rootFunc.
 +    *
 +    *  \param rootFunc A callback that can be used to add extra
 +    *  packages to the root set.
 +    *
 +    *  \return \b false if an error occured.
 +    */
 +   bool MarkRequired(InRootSetFunc &rootFunc);
 +
 +   /** \brief Set the StateCache::Garbage flag on all packages that
 +    *  should be removed.
 +    *
 +    *  Packages that were not marked by the last call to #MarkRequired
 +    *  are tested to see whether they are actually garbage.  If so,
 +    *  they are marked as such.
 +    *
 +    *  \return \b false if an error occured.
 +    */
 +   bool Sweep();
 +
 +   public:
     
     // These flags are used in DepState
     enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
        
     enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
     enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
 +
 +   /** \brief Represents an active action group.
 +    *
 +    *  An action group is a group of actions that are currently being
 +    *  performed.  While an active group is active, certain routine
 +    *  clean-up actions that would normally be performed after every
 +    *  cache operation are delayed until the action group is
 +    *  completed.  This is necessary primarily to avoid inefficiencies
 +    *  when modifying a large number of packages at once.
 +    *
 +    *  This class represents an active action group.  Creating an
 +    *  instance will create an action group; destroying one will
 +    *  destroy the corresponding action group.
 +    *
 +    *  The following operations are suppressed by this class:
 +    *
 +    *    - Keeping the Marked and Garbage flags up to date.
 +    *
 +    *  \note This can be used in the future to easily accumulate
 +    *  atomic actions for undo or to display "what apt did anyway";
 +    *  e.g., change the counter of how many action groups are active
 +    *  to a std::set of pointers to them and use those to store
 +    *  information about what happened in a group in the group.
 +    */
 +   class ActionGroup
 +   {
 +       pkgDepCache &cache;
 +
 +       bool released;
 +
 +       /** Action groups are noncopyable. */
 +       ActionGroup(const ActionGroup &other);
 +   public:
 +       /** \brief Create a new ActionGroup.
 +      *
 +      *  \param cache The cache that this ActionGroup should
 +      *  manipulate.
 +      *
 +      *  As long as this object exists, no automatic cleanup
 +      *  operations will be undertaken.
 +      */
 +       ActionGroup(pkgDepCache &cache);
 +
 +       /** \brief Clean up the action group before it is destroyed.
 +        *
 +        *  If it is destroyed later, no second cleanup wil be run.
 +      */
 +       void release();
 +
 +       /** \brief Destroy the action group.
 +      *
 +      *  If this is the last action group, the automatic cache
 +      *  cleanup operations will be undertaken.
 +      */
 +       ~ActionGroup();
 +   };
 +
 +   /** \brief Returns \b true for packages matching a regular
 +    *  expression in APT::NeverAutoRemove.
 +    */
 +   class DefaultRootSetFunc : public InRootSetFunc
 +   {
 +     std::vector<regex_t *> rootSetRegexp;
 +     bool constructedSuccessfully;
 +
 +   public:
 +     DefaultRootSetFunc();
 +     ~DefaultRootSetFunc();
 +
 +     /** \return \b true if the class initialized successfully, \b
 +      *  false otherwise.  Used to avoid throwing an exception, since
 +      *  APT classes generally don't.
 +      */
 +     bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
 +
 +     bool InRootSet(const pkgCache::PkgIterator &pkg);
 +   };
 +
     struct StateCache
     {
        // Epoch stripped text versions of the two version fields
        unsigned short Flags;
        unsigned short iFlags;           // Internal flags
  
 +      /** \brief \b true if this package can be reached from the root set. */
 +      bool Marked;
 +
 +      /** \brief \b true if this package is unused and should be removed.
 +       *
 +       *  This differs from !#Marked, because it is possible that some
 +       *  unreachable packages will be protected from becoming
 +       *  garbage.
 +       */
 +      bool Garbage;
 +
        // Various tree indicators
        signed char Status;              // -1,0,1,2
        unsigned char Mode;              // ModeList
        inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;};
        inline bool Held() const {return Status != 0 && Keep();};
        inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
 +      inline bool NowPolicyBroken() const {return (DepState & DepNowPolicy) != DepNowPolicy;};
        inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
 +      inline bool InstPolicyBroken() const {return (DepState & DepInstPolicy) != DepInstPolicy;};
        inline bool Install() const {return Mode == ModeInstall;};
        inline VerIterator InstVerIter(pkgCache &Cache)
                  {return VerIterator(Cache,InstallVer);};
        
        virtual ~Policy() {};
     };
 +
 +   private:
 +   /** The number of open "action groups"; certain post-action
 +    *  operations are suppressed if this number is > 0.
 +    */
 +   int group_level;
 +
 +   friend class ActionGroup;
       
     protected:
  
     unsigned long iDelCount;
     unsigned long iKeepCount;
     unsigned long iBrokenCount;
 +   unsigned long iPolicyBrokenCount;
     unsigned long iBadCount;
     
     Policy *delLocalPolicy;           // For memory clean up..
     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);
 +   /** \return A function identifying packages in the root set other
 +    *  than manually installed packages and essential packages, or \b
 +    *  NULL if an error occurs.
 +    *
 +    *  \todo Is this the best place for this function?  Perhaps the
 +    *  settings for mark-and-sweep should be stored in a single
 +    *  external class?
 +    */
 +   virtual InRootSetFunc *GetRootSetFunc();
 +
 +   /** \return \b true if the garbage collector should follow recommendations.
 +    */
 +   virtual bool MarkFollowsRecommends();
 +
 +   /** \return \b true if the garbage collector should follow suggestions.
 +    */
 +   virtual bool MarkFollowsSuggests();
 +
 +   /** \brief Update the Marked and Garbage fields of all packages.
 +    *
 +    *  This routine is implicitly invoked after all state manipulators
 +    *  and when an ActionGroup is destroyed.  It invokes #MarkRequired
 +    *  and #Sweep to do its dirty work.
 +    *
 +    *  \param rootFunc A predicate that returns \b true for packages
 +    *  that should be added to the root set.
 +    */
 +   bool MarkAndSweep(InRootSetFunc &rootFunc)
 +   {
 +     return MarkRequired(rootFunc) && Sweep();
 +   }
 +
 +   bool MarkAndSweep()
 +   {
 +     std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
 +     if(f.get() != NULL)
 +       return MarkAndSweep(*f.get());
 +     else
 +       return false;
 +   }
 +
 +   /** \name State Manipulators
 +    */
 +   // @{
 +   void MarkKeep(PkgIterator const &Pkg, bool Soft = false,
 +               bool FromUser = true);
     void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
     void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
 -                  unsigned long Depth = 0);
 +                  unsigned long Depth = 0, bool FromUser = true,
 +                  bool ForceImportantDeps = false);
     void SetReInstall(PkgIterator const &Pkg,bool To);
     void SetCandidateVersion(VerIterator TargetVer);
 +
 +   /** Set the "is automatically installed" flag of Pkg. */
 +   void MarkAuto(const PkgIterator &Pkg, bool Auto);
 +   // @}
     
     // This is for debuging
     void Update(OpProgress *Prog = 0);
 +
 +   // read persistent states
 +   bool readStateFile(OpProgress *prog);
 +   bool writeStateFile(OpProgress *prog, bool InstalledOnly=false);
     
     // Size queries
     inline double UsrSize() {return iUsrSize;};
     inline unsigned long KeepCount() {return iKeepCount;};
     inline unsigned long InstCount() {return iInstCount;};
     inline unsigned long BrokenCount() {return iBrokenCount;};
 +   inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;};
     inline unsigned long BadCount() {return iBadCount;};
  
     bool Init(OpProgress *Prog);
diff --combined apt-pkg/indexfile.cc
index fad38772b606c58a53763f803eb524b695c1b61b,63f692c1d5397a93f5fcecab83f53a43c8530029..2dda2d89223959d7a02648a5f3e1bf0bcbf89780
@@@ -8,15 -8,8 +8,11 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/indexfile.h"
- #endif
 +#include <apt-pkg/configuration.h>
  #include <apt-pkg/indexfile.h>
  #include <apt-pkg/error.h>
 +
 +#include <clocale>
                                                                        /*}}}*/
  
  // Global list of Item supported
@@@ -70,63 -63,3 +66,63 @@@ string pkgIndexFile::SourceInfo(pkgSrcR
     return string();
  }
                                                                        /*}}}*/
 +// IndexFile::TranslationsAvailable - Check if will use Translation    /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +bool pkgIndexFile::TranslationsAvailable()
 +{
 +  const string Translation = _config->Find("APT::Acquire::Translation", "environment");
 +  
 +  if (Translation.compare("none") != 0)
 +    return CheckLanguageCode(LanguageCode().c_str());
 +  else
 +    return false;
 +}
 +                                                                      /*}}}*/
 +// IndexFile::CheckLanguageCode - Check the Language Code             /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +/* common cases: de_DE, de_DE@euro, de_DE.UTF-8, de_DE.UTF-8@euro,
 +                 de_DE.ISO8859-1, tig_ER
 +                 more in /etc/gdm/locale.conf 
 +*/
 +
 +bool pkgIndexFile::CheckLanguageCode(const char *Lang)
 +{
 +  if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_'))
 +    return true;
 +
 +  if (strcmp(Lang,"C") != 0)
 +    _error->Warning("Wrong language code %s", Lang);
 +
 +  return false;
 +}
 +                                                                      /*}}}*/
 +// IndexFile::LanguageCode - Return the Language Code                 /*{{{*/
 +// ---------------------------------------------------------------------
 +/* return the language code */
 +string pkgIndexFile::LanguageCode()
 +{
 +  const string Translation = _config->Find("APT::Acquire::Translation", "environment");
 +
 +  if (Translation.compare("environment") == 0) 
 +  {
 +     string lang = std::setlocale(LC_MESSAGES,NULL);
 +
 +     // we have a mapping of the language codes that contains all the language
 +     // codes that need the country code as well 
 +     // (like pt_BR, pt_PT, sv_SE, zh_*, en_*)
 +     char *need_full_langcode[] = { "pt","sv","zh","en", NULL };
 +     for(char **s = need_full_langcode;*s != NULL; s++)
 +      if(lang.find(*s) == 0)
 +         return lang.substr(0,5);
 +     
 +     if(lang.size() > 2)
 +      return lang.substr(0,2);
 +     else
 +      return lang;
 +  }
 +  else 
 +     return Translation;
 +}
 +                                                                      /*}}}*/
diff --combined apt-pkg/indexfile.h
index d5d1cf57aa6ec55bb126229f17aa044b44aee60f,f1c0268b89274c991b2ec2ca37ee400d07bdc6b1..3cc501629e62b721fc7d2614ab0b21ed72405264
@@@ -5,11 -5,10 +5,11 @@@
  
     Index File - Abstraction for an index of archive/source file.
     
 -   There are 3 primary sorts of index files, all represented by this 
 +   There are 4 primary sorts of index files, all represented by this 
     class:
     
     Binary index files 
 +   Binary translation files 
     Bianry index files decribing the local system
     Source index files
     
@@@ -22,9 -21,6 +22,6 @@@
  #ifndef PKGLIB_INDEXFILE_H
  #define PKGLIB_INDEXFILE_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/indexfile.h"
- #endif
  
  #include <string>
  #include <apt-pkg/pkgcache.h>
@@@ -81,10 -77,6 +78,10 @@@ class pkgIndexFil
     virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;};
     virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
  
 +   static bool TranslationsAvailable();
 +   static bool CheckLanguageCode(const char *Lang);
 +   static string LanguageCode();
 +
     bool IsTrusted() const { return Trusted; };
     
     pkgIndexFile(bool Trusted): Trusted(Trusted) {};
diff --combined apt-pkg/orderlist.cc
index 61d8d914e43b3bf6a52fc54c29b251b86dfc3402,7302f02b60ffe7582ac15e4335197391df98b969..616714e2927f4cb4a674be6e9cfdba802b3f5b37
@@@ -63,9 -63,6 +63,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/orderlist.h"
- #endif 
  #include <apt-pkg/orderlist.h>
  #include <apt-pkg/depcache.h>
  #include <apt-pkg/error.h>
@@@ -491,13 -488,11 +488,13 @@@ bool pkgOrderList::VisitProvides(DepIte
         continue;
        
        if (D->Type != pkgCache::Dep::Conflicts &&
 +        D->Type != pkgCache::Dep::DpkgBreaks &&
          D->Type != pkgCache::Dep::Obsoletes &&
          Cache[Pkg].InstallVer != *I)
         continue;
        
        if ((D->Type == pkgCache::Dep::Conflicts ||
 +         D->Type == pkgCache::Dep::DpkgBreaks ||
           D->Type == pkgCache::Dep::Obsoletes) &&
          (Version *)Pkg.CurrentVer() != *I)
         continue;
@@@ -632,7 -627,6 +629,7 @@@ bool pkgOrderList::DepUnPackCrit(DepIte
         /* Forward critical dependencies MUST be correct before the 
            package can be unpacked. */
         if (D->Type != pkgCache::Dep::Conflicts &&
 +           D->Type != pkgCache::Dep::DpkgBreaks &&
             D->Type != pkgCache::Dep::Obsoletes &&
             D->Type != pkgCache::Dep::PreDepends)
            continue;
     }   
     return true;
  }
 -                                                                      /*}}}*/
 +
  // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends        /*{{{*/
  // ---------------------------------------------------------------------
  /* Critical PreDepends (also configure immediate and essential) strives to
@@@ -806,20 -800,9 +803,20 @@@ bool pkgOrderList::DepUnPackDep(DepIter
               return false;
         }
         else
 +       {
            if (D->Type == pkgCache::Dep::Depends)
               if (VisitProvides(D,false) == false)
                  return false;
 +
 +          if (D->Type == pkgCache::Dep::DpkgBreaks)
 +          {
 +             if (CheckDep(D) == true)
 +               continue;
 +
 +             if (VisitNode(D.TargetPkg()) == false)
 +               return false;
 +          }
 +       }
        }
     return true;
  }
@@@ -967,7 -950,6 +964,7 @@@ bool pkgOrderList::CheckDep(DepIterato
        /* Conflicts requires that all versions are not present, depends
           just needs one */
        if (D->Type != pkgCache::Dep::Conflicts && 
 +        D->Type != pkgCache::Dep::DpkgBreaks && 
          D->Type != pkgCache::Dep::Obsoletes)
        {
         /* Try to find something that does not have the after flag set
index 1e57d645561db47fd6afef95a2cb5757e4135c9e,8b94e120679e918743f3c80a88e141ecd2108d95..10e2858ed9f081671f1411bcfd6a43b049141448
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/packagemanager.h"
- #endif
  #include <apt-pkg/packagemanager.h>
  #include <apt-pkg/orderlist.h>
  #include <apt-pkg/depcache.h>
@@@ -95,10 -91,9 +91,10 @@@ bool pkgPackageManager::GetArchives(pkg
     be downloaded. */
  bool pkgPackageManager::FixMissing()
  {   
 +   pkgDepCache::ActionGroup group(Cache);
     pkgProblemResolver Resolve(&Cache);
     List->SetFileList(FileNames);
 -   
 +
     bool Bad = false;
     for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
     {
     
        // Okay, this file is missing and we need it. Mark it for keep 
        Bad = true;
 -      Cache.MarkKeep(I);
 +      Cache.MarkKeep(I, false, false);
     }
   
     // We have to empty the list otherwise it will not have the new changes
@@@ -632,11 -627,14 +628,11 @@@ pkgPackageManager::OrderResult pkgPacka
  // ---------------------------------------------------------------------
  /* This uses the filenames in FileNames and the information in the
     DepCache to perform the installation of packages.*/
 -pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int status_fd)
 +pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd)
  {
 -   OrderResult Res = OrderInstall();
 -   if(Debug)
 -      std::clog << "OrderInstall() returned: " << Res << std::endl;
 -   if (Res != Failed)
 -      if (Go(status_fd) == false)
 -       return Failed;
 -   return Res;
 +   if(DoInstallPreFork() == Failed)
 +      return Failed;
 +   
 +   return DoInstallPostFork(statusFd);
  }
                                                                        /*}}}*/
diff --combined apt-pkg/packagemanager.h
index 48f53576cf981517abd93f20be92a01e9ad686cf,35cdca913d26cdbba546063e345a67d04b6cf4fd..53600fb61acc32a4755528fc945901aea7729481
  #ifndef PKGLIB_PACKAGEMANAGER_H
  #define PKGLIB_PACKAGEMANAGER_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/packagemanager.h"
- #endif
  
  #include <string>
 +#include <iostream>
  #include <apt-pkg/pkgcache.h>
 +#include <apt-pkg/depcache.h>
  
  using std::string;
  
@@@ -72,39 -67,13 +69,39 @@@ class pkgPackageManager : protected pkg
     virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
     virtual bool Go(int statusFd=-1) {return true;};
     virtual void Reset() {};
 -   
 +
 +   // the result of the operation
 +   OrderResult Res;
 +
     public:
        
     // Main action members
     bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
                    pkgRecords *Recs);
 -   OrderResult DoInstall(int statusFd=-1); 
 +
 +   // Do the installation 
 +   OrderResult DoInstall(int statusFd=-1);
 +
 +   // stuff that needs to be done before the fork() of a library that
 +   // uses apt
 +   OrderResult DoInstallPreFork() {
 +      Res = OrderInstall();
 +      return Res;
 +   };
 +
 +   // stuff that needs to be done after the fork
 +   OrderResult DoInstallPostFork(int statusFd=-1) {
 +      bool goResult = Go(statusFd);
 +      if(goResult == false) 
 +       return Failed;
 +
 +      // if all was fine update the state file
 +      if(Res == Completed) {
 +       Cache.writeStateFile(NULL);
 +      }
 +      return Res;
 +   };
 +
     bool FixMissing();
     
     pkgPackageManager(pkgDepCache *Cache);
diff --combined apt-pkg/pkgcache.cc
index 93ad566419a505865d39dca3b20ed1f0898279e8,5672e60a4896b7fecf0eca290eed52b461a05ad8..7e3b9d78c9a5a58ebbb8913d69a5b421dc5f821f
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/pkgcache.h"
- #pragma implementation "apt-pkg/cacheiterators.h"
- #endif 
  #include <apt-pkg/pkgcache.h>
 +#include <apt-pkg/indexfile.h>
  #include <apt-pkg/version.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/strutl.h>
@@@ -44,7 -38,6 +39,7 @@@
  
  using std::string;
  
 +
  // Cache::Header::Header - Constructor                                        /*{{{*/
  // ---------------------------------------------------------------------
  /* Simply initialize the header */
@@@ -54,7 -47,7 +49,7 @@@ pkgCache::Header::Header(
     
     /* Whenever the structures change the major version should be bumped,
        whenever the generator changes the minor version should be bumped. */
 -   MajorVersion = 4;
 +   MajorVersion = 6;
     MinorVersion = 0;
     Dirty = false;
     
     PackageSz = sizeof(pkgCache::Package);
     PackageFileSz = sizeof(pkgCache::PackageFile);
     VersionSz = sizeof(pkgCache::Version);
 +   DescriptionSz = sizeof(pkgCache::Description);
     DependencySz = sizeof(pkgCache::Dependency);
     ProvidesSz = sizeof(pkgCache::Provides);
     VerFileSz = sizeof(pkgCache::VerFile);
 +   DescFileSz = sizeof(pkgCache::DescFile);
     
     PackageCount = 0;
     VersionCount = 0;
 +   DescriptionCount = 0;
     DependsCount = 0;
     PackageFileCount = 0;
     VerFileCount = 0;
 +   DescFileCount = 0;
     ProvidesCount = 0;
     MaxVerFileSize = 0;
 +   MaxDescFileSize = 0;
     
     FileList = 0;
     StringList = 0;
@@@ -96,10 -84,8 +91,10 @@@ bool pkgCache::Header::CheckSizes(Heade
         PackageSz == Against.PackageSz &&
         PackageFileSz == Against.PackageFileSz &&
         VersionSz == Against.VersionSz &&
 +       DescriptionSz == Against.DescriptionSz &&
         DependencySz == Against.DependencySz &&
         VerFileSz == Against.VerFileSz &&
 +       DescFileSz == Against.DescFileSz &&
         ProvidesSz == Against.ProvidesSz)
        return true;
     return false;
@@@ -124,10 -110,8 +119,10 @@@ bool pkgCache::ReMap(
     HeaderP = (Header *)Map.Data();
     PkgP = (Package *)Map.Data();
     VerFileP = (VerFile *)Map.Data();
 +   DescFileP = (DescFile *)Map.Data();
     PkgFileP = (PackageFile *)Map.Data();
     VerP = (Version *)Map.Data();
 +   DescP = (Description *)Map.Data();
     ProvideP = (Provides *)Map.Data();
     DepP = (Dependency *)Map.Data();
     StringItemP = (StringItem *)Map.Data();
@@@ -228,8 -212,8 +223,8 @@@ const char *pkgCache::DepType(unsigned 
  {
     const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
                            _("Recommends"),_("Conflicts"),_("Replaces"),
 -                          _("Obsoletes")};
 -   if (Type < 8)
 +                          _("Obsoletes"),_("Breaks")};
 +   if (Type < sizeof(Types)/sizeof(*Types))
        return Types[Type];
     return "";
  }
@@@ -246,11 -230,11 +241,11 @@@ const char *pkgCache::Priority(unsigne
     return 0;
  }
                                                                        /*}}}*/
 -
  // Bases for iterator classes                                         /*{{{*/
  void pkgCache::VerIterator::_dummy() {}
  void pkgCache::DepIterator::_dummy() {}
  void pkgCache::PrvIterator::_dummy() {}
 +void pkgCache::DescIterator::_dummy() {}
                                                                        /*}}}*/
  // PkgIterator::operator ++ - Postfix incr                            /*{{{*/
  // ---------------------------------------------------------------------
@@@ -292,11 -276,10 +287,11 @@@ pkgCache::PkgIterator::OkState pkgCache
  // DepIterator::IsCritical - Returns true if the dep is important     /*{{{*/
  // ---------------------------------------------------------------------
  /* Currently critical deps are defined as depends, predepends and
 -   conflicts. */
 +   conflicts (including dpkg's Breaks fields). */
  bool pkgCache::DepIterator::IsCritical()
  {
     if (Dep->Type == pkgCache::Dep::Conflicts ||
 +       Dep->Type == pkgCache::Dep::DpkgBreaks ||
         Dep->Type == pkgCache::Dep::Obsoletes ||
         Dep->Type == pkgCache::Dep::Depends ||
         Dep->Type == pkgCache::Dep::PreDepends)
@@@ -382,7 -365,6 +377,7 @@@ pkgCache::Version **pkgCache::DepIterat
            continue;
  
         if ((Dep->Type == pkgCache::Dep::Conflicts ||
 +            Dep->Type == pkgCache::Dep::DpkgBreaks ||
              Dep->Type == pkgCache::Dep::Obsoletes) &&
             ParentPkg() == I.ParentPkg())
            continue;
            continue;
         
         if ((Dep->Type == pkgCache::Dep::Conflicts ||
 +            Dep->Type == pkgCache::Dep::DpkgBreaks ||
              Dep->Type == pkgCache::Dep::Obsoletes) &&
             ParentPkg() == I.OwnerPkg())
            continue;
@@@ -613,20 -594,3 +608,20 @@@ string pkgCache::PkgFileIterator::RelSt
     return Res;
  }
                                                                        /*}}}*/
 +// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
 +// ---------------------------------------------------------------------
 +/* return a DescIter for the current locale or the default if none is 
 + * found
 + */
 +pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
 +{
 +   pkgCache::DescIterator DescDefault = DescriptionList();
 +   pkgCache::DescIterator Desc = DescDefault;
 +   for (; Desc.end() == false; Desc++)
 +      if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
 +       break;
 +   if (Desc.end() == true) Desc = DescDefault;
 +   return Desc;
 +};
 +
 +                                                                      /*}}}*/
diff --combined apt-pkg/pkgcache.h
index 970759492f70674cc09425fbe45d2dbf05813262,8e7fc252c88aab320209affa3f7b321ba98ff69d..83b7548a3da01e7ab5b52492f882e31fd387a826
@@@ -19,9 -19,6 +19,6 @@@
  #ifndef PKGLIB_PKGCACHE_H
  #define PKGLIB_PKGCACHE_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/pkgcache.h"
- #endif 
  
  #include <string>
  #include <time.h>
@@@ -38,42 -35,32 +35,42 @@@ class pkgCach
     struct Package;
     struct PackageFile;
     struct Version;
 +   struct Description;
     struct Provides;
     struct Dependency;
     struct StringItem;
     struct VerFile;
 +   struct DescFile;
     
     // Iterators
     class PkgIterator;
     class VerIterator;
 +   class DescIterator;
     class DepIterator;
     class PrvIterator;
     class PkgFileIterator;
     class VerFileIterator;
 +   class DescFileIterator;
     friend class PkgIterator;
     friend class VerIterator;
 +   friend class DescInterator;
     friend class DepIterator;
     friend class PrvIterator;
     friend class PkgFileIterator;
     friend class VerFileIterator;
 +   friend class DescFileIterator;
     
     class Namespace;
     
     // These are all the constants used in the cache structures
 +
 +   // WARNING - if you change these lists you must also edit
 +   // the stringification in pkgcache.cc and also consider whether
 +   // the cache file will become incompatible.
     struct Dep
     {
        enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
 -       Conflicts=5,Replaces=6,Obsoletes=7};
 +       Conflicts=5,Replaces=6,Obsoletes=7,DpkgBreaks=8};
        enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
         Greater=0x4,Equals=0x5,NotEquals=0x6};
     };
     Header *HeaderP;
     Package *PkgP;
     VerFile *VerFileP;
 +   DescFile *DescFileP;
     PackageFile *PkgFileP;
     Version *VerP;
 +   Description *DescP;
     Provides *ProvideP;
     Dependency *DepP;
     StringItem *StringItemP;
@@@ -163,20 -148,16 +160,20 @@@ struct pkgCache::Heade
     unsigned short PackageSz;
     unsigned short PackageFileSz;
     unsigned short VersionSz;
 +   unsigned short DescriptionSz;
     unsigned short DependencySz;
     unsigned short ProvidesSz;
     unsigned short VerFileSz;
 +   unsigned short DescFileSz;
     
     // Structure counts
     unsigned long PackageCount;
     unsigned long VersionCount;
 +   unsigned long DescriptionCount;
     unsigned long DependsCount;
     unsigned long PackageFileCount;
     unsigned long VerFileCount;
 +   unsigned long DescFileCount;
     unsigned long ProvidesCount;
     
     // Offsets
     map_ptrloc VerSysName;            // StringTable
     map_ptrloc Architecture;          // StringTable
     unsigned long MaxVerFileSize;
 +   unsigned long MaxDescFileSize;
  
     /* Allocation pools, there should be one of these for each structure
        excluding the header */
 -   DynamicMMap::Pool Pools[7];
 +   DynamicMMap::Pool Pools[8];
     
     // Rapid package name lookup
     map_ptrloc HashTable[2*1048];
@@@ -210,7 -190,7 +207,7 @@@ struct pkgCache::Packag
     map_ptrloc NextPackage;       // Package
     map_ptrloc RevDepends;        // Dependency
     map_ptrloc ProvidesList;      // Provides
 -   
 +
     // Install/Remove/Purge etc
     unsigned char SelectedState;     // What
     unsigned char InstState;         // Flags
@@@ -249,14 -229,6 +246,14 @@@ struct pkgCache::VerFil
     unsigned short Size;
  };
  
 +struct pkgCache::DescFile
 +{
 +   map_ptrloc File;           // PackageFile
 +   map_ptrloc NextFile;       // PkgVerFile
 +   map_ptrloc Offset;         // File offset
 +   unsigned short Size;
 +};
 +
  struct pkgCache::Version
  {
     map_ptrloc VerStr;            // Stringtable
     // Lists
     map_ptrloc FileList;          // VerFile
     map_ptrloc NextVer;           // Version
 +   map_ptrloc DescriptionList;   // Description
     map_ptrloc DependsList;       // Dependency
     map_ptrloc ParentPkg;         // Package
     map_ptrloc ProvidesList;      // Provides
     unsigned char Priority;
  };
  
 +struct pkgCache::Description
 +{
 +   // Language Code store the description translation language code. If
 +   // the value has a 0 lenght then this is readed using the Package
 +   // file else the Translation-CODE are used.
 +   map_ptrloc language_code;     // StringTable
 +   map_ptrloc md5sum;            // StringTable
 +
 +   // Linked list 
 +   map_ptrloc FileList;          // DescFile
 +   map_ptrloc NextDesc;          // Description
 +   map_ptrloc ParentPkg;         // Package
 +
 +   unsigned short ID;
 +};
 +
  struct pkgCache::Dependency
  {
     map_ptrloc Version;         // Stringtable
@@@ -341,13 -296,11 +338,13 @@@ class pkgCache::Namespac
  
     typedef pkgCache::PkgIterator PkgIterator;
     typedef pkgCache::VerIterator VerIterator;
 +   typedef pkgCache::DescIterator DescIterator;
     typedef pkgCache::DepIterator DepIterator;
     typedef pkgCache::PrvIterator PrvIterator;
     typedef pkgCache::PkgFileIterator PkgFileIterator;
     typedef pkgCache::VerFileIterator VerFileIterator;   
     typedef pkgCache::Version Version;
 +   typedef pkgCache::Description Description;
     typedef pkgCache::Package Package;
     typedef pkgCache::Header Header;
     typedef pkgCache::Dep Dep;
diff --combined apt-pkg/pkgcachegen.cc
index 8ec6a171975ce1a28e7eee26beadbcc1a32adf38,1c93b32a35eb6b5b09ad2bac03718587d2f34233..ce9b96980c3792b16a244843510b64c9408207a8
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/pkgcachegen.h"
- #endif
  #define APT_COMPATIBILITY 986
  
  #include <apt-pkg/pkgcachegen.h>
@@@ -26,8 -22,6 +22,8 @@@
  #include <apt-pkg/sptr.h>
  #include <apt-pkg/pkgsystem.h>
  
 +#include <apt-pkg/tagfile.h>
 +
  #include <apti18n.h>
  
  #include <vector>
@@@ -127,46 -121,16 +123,46 @@@ bool pkgCacheGenerator::MergeList(ListP
        string Version = List.Version();
        if (Version.empty() == true)
        {
 +       // we first process the package, then the descriptions
 +       // (this has the bonus that we get MMap error when we run out
 +       //  of MMap space)
         if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
            return _error->Error(_("Error occurred while processing %s (UsePackage1)"),
                                 PackageName.c_str());
 +
 +       // Find the right version to write the description
 +       MD5SumValue CurMd5 = List.Description_md5();
 +       pkgCache::VerIterator Ver = Pkg.VersionList();
 +       map_ptrloc *LastVer = &Pkg->VersionList;
 +
 +       for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) 
 +       {
 +          pkgCache::DescIterator Desc = Ver.DescriptionList();
 +          map_ptrloc *LastDesc = &Ver->DescriptionList;
 +
 +          for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++)
 +          {
 +
 +             if (MD5SumValue(Desc.md5()) == CurMd5) 
 +               {
 +                // Add new description
 +                *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
 +                Desc->ParentPkg = Pkg.Index();
 +                
 +                if (NewFileDesc(Desc,List) == false)
 +                   return _error->Error(_("Error occured while processing %s (NewFileDesc1)"),PackageName.c_str());
 +                break;
 +             }
 +          }
 +       }
 +
         continue;
        }
  
        pkgCache::VerIterator Ver = Pkg.VersionList();
 -      map_ptrloc *Last = &Pkg->VersionList;
 +      map_ptrloc *LastVer = &Pkg->VersionList;
        int Res = 1;
 -      for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
 +      for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
        {
         Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
         if (Res >= 0)
        // Skip to the end of the same version set.
        if (Res == 0)
        {
 -       for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
 +       for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
         {
            Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
            if (Res != 0)
        }
  
        // Add a new version
 -      *Last = NewVersion(Ver,Version,*Last);
 +      *LastVer = NewVersion(Ver,Version,*LastVer);
        Ver->ParentPkg = Pkg.Index();
        Ver->Hash = Hash;
 +
        if (List.NewVersion(Ver) == false)
         return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
                              PackageName.c_str());
         FoundFileDeps |= List.HasFileDeps();
         return true;
        }      
 +
 +      /* Record the Description data. Description data always exist in
 +       Packages and Translation-* files. */
 +      pkgCache::DescIterator Desc = Ver.DescriptionList();
 +      map_ptrloc *LastDesc = &Ver->DescriptionList;
 +      
 +      // Skip to the end of description set
 +      for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++);
 +
 +      // Add new description
 +      *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
 +      Desc->ParentPkg = Pkg.Index();
 +
 +      if (NewFileDesc(Desc,List) == false)
 +       return _error->Error(_("Error occured while processing %s (NewFileDesc2)"),PackageName.c_str());
     }
  
     FoundFileDeps |= List.HasFileDeps();
     if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
        return _error->Error(_("Wow, you exceeded the number of versions "
                             "this APT is capable of."));
 +   if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
 +      return _error->Error(_("Wow, you exceeded the number of descriptions "
 +                           "this APT is capable of."));
     if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
        return _error->Error(_("Wow, you exceeded the number of dependencies "
                             "this APT is capable of."));
@@@ -322,7 -267,7 +318,7 @@@ bool pkgCacheGenerator::NewPackage(pkgC
     Pkg = Cache.FindPkg(Name);
     if (Pkg.end() == false)
        return true;
 -       
 +
     // Get a structure
     unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
     if (Package == 0)
@@@ -400,62 -345,6 +396,62 @@@ unsigned long pkgCacheGenerator::NewVer
     return Version;
  }
                                                                        /*}}}*/
 +// CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
 +                                 ListParser &List)
 +{
 +   if (CurrentFile == 0)
 +      return true;
 +   
 +   // Get a structure
 +   unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
 +   if (DescFile == 0)
 +      return 0;
 +
 +   pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
 +   DF->File = CurrentFile - Cache.PkgFileP;
 +
 +   // Link it to the end of the list
 +   map_ptrloc *Last = &Desc->FileList;
 +   for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; D++)
 +      Last = &D->NextFile;
 +
 +   DF->NextFile = *Last;
 +   *Last = DF.Index();
 +   
 +   DF->Offset = List.Offset();
 +   DF->Size = List.Size();
 +   if (Cache.HeaderP->MaxDescFileSize < DF->Size)
 +      Cache.HeaderP->MaxDescFileSize = DF->Size;
 +   Cache.HeaderP->DescFileCount++;
 +   
 +   return true;
 +}
 +                                                                      /*}}}*/
 +// CacheGenerator::NewDescription - Create a new Description          /*{{{*/
 +// ---------------------------------------------------------------------
 +/* This puts a description structure in the linked list */
 +map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 +                                          const string &Lang, const MD5SumValue &md5sum,
 +                                          map_ptrloc Next)
 +{
 +   // Get a structure
 +   map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description));
 +   if (Description == 0)
 +      return 0;
 +
 +   // Fill it in
 +   Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
 +   Desc->NextDesc = Next;
 +   Desc->ID = Cache.HeaderP->DescriptionCount++;
 +   Desc->language_code = Map.WriteString(Lang);
 +   Desc->md5sum = Map.WriteString(md5sum.Value());
 +
 +   return Description;
 +}
 +                                                                      /*}}}*/
  // ListParser::NewDepends - Create a dependency element                       /*{{{*/
  // ---------------------------------------------------------------------
  /* This creates a dependency element in the tree. It is linked to the
@@@ -678,10 -567,8 +674,10 @@@ static bool CheckValidity(const string 
      
        if ((*Start)->Exists() == false)
        {
 +#if 0 // mvo: we no longer give a message here (Default Sources spec)
         _error->WarningE("stat",_("Couldn't stat source package list %s"),
                          (*Start)->Describe().c_str());
 +#endif
         continue;
        }
  
        pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
        if (File.end() == true)
         return false;
 -      
 +
        Visited[File->ID] = true;
     }
     
@@@ -785,7 -672,7 +781,7 @@@ static bool BuildCache(pkgCacheGenerato
  bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
                        MMap **OutMap,bool AllowMem)
  {
 -   unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024);
 +   unsigned long MapSize = _config->FindI("APT::Cache-Limit",16*1024*1024);
     
     vector<pkgIndexFile *> Files;
     for (vector<metaIndex *>::const_iterator i = List.begin();
  /* */
  bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
  {
 -   unsigned long MapSize = _config->FindI("APT::Cache-Limit",8*1024*1024);
 +   unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024);
     vector<pkgIndexFile *> Files;
     unsigned long EndOfSource = Files.size();
     if (_system->AddStatusFiles(Files) == false)
diff --combined apt-pkg/pkgcachegen.h
index fae1a60a6d0ab153c3e946e8a269bf5bdad33c97,70616c0a8f9bfab3e1369355daf65a8ed48ed802..a47b097b3185ead0650e4a3165df0345a4de6aca
  #ifndef PKGLIB_PKGCACHEGEN_H
  #define PKGLIB_PKGCACHEGEN_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/pkgcachegen.h"
- #endif 
  
  #include <apt-pkg/pkgcache.h>
 +#include <apt-pkg/md5.h>
  
  class pkgSourceList;
  class OpProgress;
@@@ -56,9 -52,7 +53,9 @@@ class pkgCacheGenerato
     
     bool NewPackage(pkgCache::PkgIterator &Pkg,const string &Pkg);
     bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
 +   bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
     unsigned long NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next);
 +   map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const string &Lang,const MD5SumValue &md5sum,map_ptrloc Next);
  
     public:
  
@@@ -111,9 -105,6 +108,9 @@@ class pkgCacheGenerator::ListParse
     virtual string Package() = 0;
     virtual string Version() = 0;
     virtual bool NewVersion(pkgCache::VerIterator Ver) = 0;
 +   virtual string Description() = 0;
 +   virtual string DescriptionLanguage() = 0;
 +   virtual MD5SumValue Description_md5() = 0;
     virtual unsigned short VersionHash() = 0;
     virtual bool UsePackage(pkgCache::PkgIterator Pkg,
                           pkgCache::VerIterator Ver) = 0;
diff --combined apt-pkg/pkgrecords.cc
index 456b5aef41701e7f3a07bac6a51dad45d1378ec3,dc43735a6f58628f24444f301ea42035ea1475cc..d251bee413c3034ade836a33c3afc41214c3c2ae
@@@ -9,9 -9,6 +9,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/pkgrecords.h"
- #endif
  #include <apt-pkg/pkgrecords.h>
  #include <apt-pkg/indexfile.h>
  #include <apt-pkg/error.h>
  // Records::pkgRecords - Constructor                                  /*{{{*/
  // ---------------------------------------------------------------------
  /* This will create the necessary structures to access the status files */
 -pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache), Files(0)
 +pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache),
 +  Files(Cache.HeaderP->PackageFileCount)
  {
 -   Files = new Parser *[Cache.HeaderP->PackageFileCount];
 -   memset(Files,0,sizeof(*Files)*Cache.HeaderP->PackageFileCount);
 -   
     for (pkgCache::PkgFileIterator I = Cache.FileBegin(); 
        I.end() == false; I++)
     {
  /* */
  pkgRecords::~pkgRecords()
  {
 -   for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
 -      delete Files[I];
 -   delete [] Files;
 +   for ( vector<Parser*>::iterator it = Files.begin();
 +     it != Files.end();
 +     ++it)
 +   {
 +      delete *it;
 +   }
 +
  }
                                                                        /*}}}*/
  // Records::Lookup - Get a parser for the package version file                /*{{{*/
@@@ -65,12 -60,3 +62,12 @@@ pkgRecords::Parser &pkgRecords::Lookup(
     return *Files[Ver.File()->ID];
  }
                                                                        /*}}}*/
 +// Records::Lookup - Get a parser for the package description file    /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc)
 +{
 +   Files[Desc.File()->ID]->Jump(Desc);
 +   return *Files[Desc.File()->ID];
 +}
 +                                                                      /*}}}*/
diff --combined apt-pkg/pkgrecords.h
index ad3946c1bee6bbde736e88ca4e4ee18616b05140,d431101fe05ebcffb6926e95d1c88f6d2183b340..bae5284abe3dc3712dea5477992ca52639e269b7
  #ifndef PKGLIB_PKGRECORDS_H
  #define PKGLIB_PKGRECORDS_H
  
- #ifdef __GNUG__
- #pragma interface "apt-pkg/pkgrecords.h"
- #endif 
  
  #include <apt-pkg/pkgcache.h>
  #include <apt-pkg/fileutl.h>
 +#include <vector>
  
  class pkgRecords
  {
     private:
     
     pkgCache &Cache;
 -   Parser **Files;
 -      
 +   std::vector<Parser *>Files;
 +
     public:
  
     // Lookup function
     Parser &Lookup(pkgCache::VerFileIterator const &Ver);
 +   Parser &Lookup(pkgCache::DescFileIterator const &Desc);
  
     // Construct destruct
     pkgRecords(pkgCache &Cache);
@@@ -51,7 -46,6 +48,7 @@@ class pkgRecords::Parse
     protected:
     
     virtual bool Jump(pkgCache::VerFileIterator const &Ver) = 0;
 +   virtual bool Jump(pkgCache::DescFileIterator const &Desc) = 0;
     
     public:
     friend class pkgRecords;
diff --combined apt-pkg/policy.cc
index 35a50425b7a45017cc8144aca76e25d6a1bdd014,795f1d7878822cdc0f3c132cfe7e0197e6fcd661..8b083fd444aa80e8d8b9c4314a12a7802c879470
@@@ -23,9 -23,6 +23,6 @@@
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/policy.h"
- #endif
  #include <apt-pkg/policy.h>
  #include <apt-pkg/configuration.h>
  #include <apt-pkg/tagfile.h>
@@@ -36,7 -33,6 +33,7 @@@
  #include <apti18n.h>
  
  #include <iostream>
 +#include <sstream>
                                                                        /*}}}*/
  
  using namespace std;
@@@ -301,13 -297,7 +298,13 @@@ bool ReadPinFile(pkgPolicy &Plcy,strin
           continue;
        }
  
 -      Plcy.CreatePin(Type,Name,string(Word,End),priority);
 +      istringstream s(Name);
 +      string pkg;
 +      while(!s.eof())
 +      {
 +       s >> pkg;
 +         Plcy.CreatePin(Type, pkg, string(Word,End),priority);
 +      };
     }
  
     Plcy.InitDefaults();
diff --combined apt-pkg/tagfile.cc
index 8700dd17d5d99ed5decd88378f16768ffc3f1e5f,85e6abfd77463eaf58681a7949d51ae0ed18ebf4..0ae6950f3e2dd350a89bbae1432e273f2b71f84b
     ##################################################################### */
                                                                        /*}}}*/
  // Include Files                                                      /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/tagfile.h"
- #endif
  #include <apt-pkg/tagfile.h>
  #include <apt-pkg/error.h>
  #include <apt-pkg/strutl.h>
@@@ -411,7 -407,6 +407,7 @@@ static const char *iTFRewritePackageOrd
                            "Section",
                            "Installed-Size",
                            "Maintainer",
 +                          "Original-Maintainer",
                            "Architecture",
                            "Source",
                            "Version",
                            "Recommends",
                            "Suggests",
                            "Conflicts",
 +                          "Breaks",
                            "Conffiles",
                            "Filename",
                            "Size",
@@@ -441,7 -435,6 +437,7 @@@ static const char *iTFRewriteSourceOrde
                                        "Priority",
                                        "Section",
                                        "Maintainer",
 +                                    "Original-Maintainer",
                                        "Build-Depends",
                                        "Build-Depends-Indep",
                                        "Build-Conflicts",
diff --combined po/apt-all.pot
index b55c31ff4d320fdc59c53c8802ab3b8eddb2ada9,4c354136a73fe173a486eda6c07207a4ba4c0e95..addf713f88c496c490d622a30d0203e14d0b31d8
@@@ -7,7 -7,7 +7,7 @@@ msgid "
  msgstr ""
  "Project-Id-Version: PACKAGE VERSION\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2007-04-27 15:16+0200\n"
+ "POT-Creation-Date: 2006-10-02 15:46+0200\n"
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@@ -1477,16 -1477,16 +1477,16 @@@ msgstr "
  msgid "Wrong CD-ROM"
  msgstr ""
  
 -#: methods/cdrom.cc:164
 +#: methods/cdrom.cc:166
  #, c-format
  msgid "Unable to unmount the CD-ROM in %s, it may still be in use."
  msgstr ""
  
 -#: methods/cdrom.cc:169
 +#: methods/cdrom.cc:171
  msgid "Disk not found."
  msgstr ""
  
 -#: methods/cdrom.cc:177 methods/file.cc:79 methods/rsh.cc:264
 +#: methods/cdrom.cc:179 methods/file.cc:79 methods/rsh.cc:264
  msgid "File not found"
  msgstr ""
  
@@@ -1621,7 -1621,7 +1621,7 @@@ msgstr "
  msgid "Unable to accept connection"
  msgstr ""
  
 -#: methods/ftp.cc:864 methods/http.cc:958 methods/rsh.cc:303
 +#: methods/ftp.cc:864 methods/http.cc:959 methods/rsh.cc:303
  msgid "Problem hashing file"
  msgstr ""
  
@@@ -1752,76 -1752,76 +1752,76 @@@ msgstr "
  msgid "Read error from %s process"
  msgstr ""
  
 -#: methods/http.cc:376
 +#: methods/http.cc:377
  msgid "Waiting for headers"
  msgstr ""
  
 -#: methods/http.cc:522
 +#: methods/http.cc:523
  #, c-format
  msgid "Got a single header line over %u chars"
  msgstr ""
  
 -#: methods/http.cc:530
 +#: methods/http.cc:531
  msgid "Bad header line"
  msgstr ""
  
 -#: methods/http.cc:549 methods/http.cc:556
 +#: methods/http.cc:550 methods/http.cc:557
  msgid "The HTTP server sent an invalid reply header"
  msgstr ""
  
 -#: methods/http.cc:585
 +#: methods/http.cc:586
  msgid "The HTTP server sent an invalid Content-Length header"
  msgstr ""
  
 -#: methods/http.cc:600
 +#: methods/http.cc:601
  msgid "The HTTP server sent an invalid Content-Range header"
  msgstr ""
  
 -#: methods/http.cc:602
 +#: methods/http.cc:603
  msgid "This HTTP server has broken range support"
  msgstr ""
  
 -#: methods/http.cc:626
 +#: methods/http.cc:627
  msgid "Unknown date format"
  msgstr ""
  
 -#: methods/http.cc:773
 +#: methods/http.cc:774
  msgid "Select failed"
  msgstr ""
  
 -#: methods/http.cc:778
 +#: methods/http.cc:779
  msgid "Connection timed out"
  msgstr ""
  
 -#: methods/http.cc:801
 +#: methods/http.cc:802
  msgid "Error writing to output file"
  msgstr ""
  
 -#: methods/http.cc:832
 +#: methods/http.cc:833
  msgid "Error writing to file"
  msgstr ""
  
 -#: methods/http.cc:860
 +#: methods/http.cc:861
  msgid "Error writing to the file"
  msgstr ""
  
 -#: methods/http.cc:874
 +#: methods/http.cc:875
  msgid "Error reading from server. Remote end closed connection"
  msgstr ""
  
 -#: methods/http.cc:876
 +#: methods/http.cc:877
  msgid "Error reading from server"
  msgstr ""
  
 -#: methods/http.cc:1107
 +#: methods/http.cc:1108
  msgid "Bad header data"
  msgstr ""
  
 -#: methods/http.cc:1124
 +#: methods/http.cc:1125
  msgid "Connection failed"
  msgstr ""
  
 -#: methods/http.cc:1215
 +#: methods/http.cc:1216
  msgid "Internal error"
  msgstr ""
  
@@@ -1894,12 -1894,12 +1894,12 @@@ msgstr "
  msgid "Syntax error %s:%u: Extra junk at end of file"
  msgstr ""
  
 -#: apt-pkg/contrib/progress.cc:154
 +#: apt-pkg/contrib/progress.cc:155
  #, c-format
  msgid "%c%s... Error!"
  msgstr ""
  
 -#: apt-pkg/contrib/progress.cc:156
 +#: apt-pkg/contrib/progress.cc:157
  #, c-format
  msgid "%c%s... Done"
  msgstr ""
@@@ -2031,84 -2031,84 +2031,84 @@@ msgstr "
  msgid "Problem syncing the file"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:126
+ #: apt-pkg/pkgcache.cc:121
  msgid "Empty package cache"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:132
+ #: apt-pkg/pkgcache.cc:127
  msgid "The package cache file is corrupted"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:137
+ #: apt-pkg/pkgcache.cc:132
  msgid "The package cache file is an incompatible version"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:142
+ #: apt-pkg/pkgcache.cc:137
  #, c-format
  msgid "This APT does not support the versioning system '%s'"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:147
+ #: apt-pkg/pkgcache.cc:142
  msgid "The package cache was built for a different architecture"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:218
+ #: apt-pkg/pkgcache.cc:213
  msgid "Depends"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:218
+ #: apt-pkg/pkgcache.cc:213
  msgid "PreDepends"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:218
+ #: apt-pkg/pkgcache.cc:213
  msgid "Suggests"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:219
+ #: apt-pkg/pkgcache.cc:214
  msgid "Recommends"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:219
+ #: apt-pkg/pkgcache.cc:214
  msgid "Conflicts"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:219
+ #: apt-pkg/pkgcache.cc:214
  msgid "Replaces"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:220
+ #: apt-pkg/pkgcache.cc:215
  msgid "Obsoletes"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:231
+ #: apt-pkg/pkgcache.cc:226
  msgid "important"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:231
+ #: apt-pkg/pkgcache.cc:226
  msgid "required"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:231
+ #: apt-pkg/pkgcache.cc:226
  msgid "standard"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:232
+ #: apt-pkg/pkgcache.cc:227
  msgid "optional"
  msgstr ""
  
- #: apt-pkg/pkgcache.cc:232
+ #: apt-pkg/pkgcache.cc:227
  msgid "extra"
  msgstr ""
  
- #: apt-pkg/depcache.cc:61 apt-pkg/depcache.cc:90
+ #: apt-pkg/depcache.cc:58 apt-pkg/depcache.cc:87
  msgid "Building dependency tree"
  msgstr ""
  
- #: apt-pkg/depcache.cc:62
+ #: apt-pkg/depcache.cc:59
  msgid "Candidate versions"
  msgstr ""
  
- #: apt-pkg/depcache.cc:91
+ #: apt-pkg/depcache.cc:88
  msgid "Dependency generation"
  msgstr ""
  
@@@ -2191,13 -2191,13 +2191,13 @@@ msgid "
  "The package %s needs to be reinstalled, but I can't find an archive for it."
  msgstr ""
  
 -#: apt-pkg/algorithms.cc:1059
 +#: apt-pkg/algorithms.cc:1066
  msgid ""
  "Error, pkgProblemResolver::Resolve generated breaks, this may be caused by "
  "held packages."
  msgstr ""
  
 -#: apt-pkg/algorithms.cc:1061
 +#: apt-pkg/algorithms.cc:1068
  msgid "Unable to correct problems, you have held broken packages."
  msgstr ""
  
@@@ -2213,12 -2213,12 +2213,12 @@@ msgstr "
  
  #. only show the ETA if it makes sense
  #. two days
 -#: apt-pkg/acquire.cc:823
 +#: apt-pkg/acquire.cc:830
  #, c-format
  msgid "Retrieving file %li of %li (%s remaining)"
  msgstr ""
  
 -#: apt-pkg/acquire.cc:825
 +#: apt-pkg/acquire.cc:832
  #, c-format
  msgid "Retrieving file %li of %li"
  msgstr ""
@@@ -2264,16 -2264,16 +2264,16 @@@ msgstr "
  msgid "You may want to run apt-get update to correct these problems"
  msgstr ""
  
 -#: apt-pkg/policy.cc:269
 +#: apt-pkg/policy.cc:270
  msgid "Invalid record in the preferences file, no Package header"
  msgstr ""
  
 -#: apt-pkg/policy.cc:291
 +#: apt-pkg/policy.cc:292
  #, c-format
  msgid "Did not understand pin type %s"
  msgstr ""
  
 -#: apt-pkg/policy.cc:299
 +#: apt-pkg/policy.cc:300
  msgid "No priority (or zero) specified for pin"
  msgstr ""
  
@@@ -2361,35 -2361,35 +2361,35 @@@ msgstr "
  msgid "rename failed, %s (%s -> %s)."
  msgstr ""
  
 -#: apt-pkg/acquire-item.cc:236 apt-pkg/acquire-item.cc:945
 +#: apt-pkg/acquire-item.cc:243 apt-pkg/acquire-item.cc:952
  msgid "MD5Sum mismatch"
  msgstr ""
  
 -#: apt-pkg/acquire-item.cc:640
 -msgid "There are no public key available for the following key IDs:\n"
 +#: apt-pkg/acquire-item.cc:647
 +msgid "There is no public key available for the following key IDs:\n"
  msgstr ""
  
 -#: apt-pkg/acquire-item.cc:753
 +#: apt-pkg/acquire-item.cc:760
  #, c-format
  msgid ""
  "I wasn't able to locate a file for the %s package. This might mean you need "
  "to manually fix this package. (due to missing arch)"
  msgstr ""
  
 -#: apt-pkg/acquire-item.cc:812
 +#: apt-pkg/acquire-item.cc:819
  #, c-format
  msgid ""
  "I wasn't able to locate file for the %s package. This might mean you need to "
  "manually fix this package."
  msgstr ""
  
 -#: apt-pkg/acquire-item.cc:848
 +#: apt-pkg/acquire-item.cc:855
  #, c-format
  msgid ""
  "The package index files are corrupted. No Filename: field for package %s."
  msgstr ""
  
 -#: apt-pkg/acquire-item.cc:935
 +#: apt-pkg/acquire-item.cc:942
  msgid "Size mismatch"
  msgstr ""
  
@@@ -2441,30 -2441,30 +2441,30 @@@ msgstr "
  msgid "Found %i package indexes, %i source indexes and %i signatures\n"
  msgstr ""
  
 -#: apt-pkg/cdrom.cc:710
 +#: apt-pkg/cdrom.cc:712
  msgid "That is not a valid name, try again.\n"
  msgstr ""
  
 -#: apt-pkg/cdrom.cc:726
 +#: apt-pkg/cdrom.cc:728
  #, c-format
  msgid ""
  "This disc is called: \n"
  "'%s'\n"
  msgstr ""
  
 -#: apt-pkg/cdrom.cc:730
 +#: apt-pkg/cdrom.cc:732
  msgid "Copying package lists..."
  msgstr ""
  
 -#: apt-pkg/cdrom.cc:754
 +#: apt-pkg/cdrom.cc:756
  msgid "Writing new source list\n"
  msgstr ""
  
 -#: apt-pkg/cdrom.cc:763
 +#: apt-pkg/cdrom.cc:765
  msgid "Source list entries for this disc are:\n"
  msgstr ""
  
 -#: apt-pkg/cdrom.cc:803
 +#: apt-pkg/cdrom.cc:807
  msgid "Unmounting CD-ROM..."
  msgstr ""