]> git.saurik.com Git - apt.git/commitdiff
merged from lp:~donkult/apt/sid
authorMichael Vogt <michael.vogt@ubuntu.com>
Wed, 9 Jun 2010 11:15:34 +0000 (13:15 +0200)
committerMichael Vogt <michael.vogt@ubuntu.com>
Wed, 9 Jun 2010 11:15:34 +0000 (13:15 +0200)
1  2 
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/acquire-method.cc
apt-pkg/deb/debsystem.cc
apt-pkg/deb/dpkgpm.cc
apt-pkg/deb/dpkgpm.h
apt-pkg/tagfile.cc
cmdline/apt-get.cc
debian/changelog
methods/http.cc
test/pre-upload-check.py

diff --combined apt-pkg/acquire-item.cc
index 8973eeddee2f467d7034ad45fd12aa5ff0f9b547,629d572a433eb5ccf7dc6853cac7138dc51ab584..4d9a152abadd3355e25561dc7717115350641687
@@@ -33,6 -33,7 +33,7 @@@
  #include <string>
  #include <sstream>
  #include <stdio.h>
+ #include <ctime>
                                                                        /*}}}*/
  
  using namespace std;
@@@ -64,7 -65,6 +65,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                  /*{{{*/
@@@ -109,7 -102,7 +110,7 @@@ void pkgAcquire::Item::Done(string Mess
  {
     // We just downloaded something..
     string FileName = LookupTag(Message,"Filename");
 -   // we only inform the Log class if it was actually not a local thing
 +   UsedMirror =  LookupTag(Message,"UsedMirror");
     if (Complete == false && !Local && FileName == DestFile)
     {
        if (Owner->Log != 0)
  
     if (FileSize == 0)
        FileSize= Size;
 -   
     Status = StatDone;
     ErrorText = string();
     Owner->Dequeue(this);
@@@ -139,49 -133,6 +140,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());
 +   }
 +}
 +
  // AcqDiffIndex::AcqDiffIndex - Constructor                           /*{{{*/
  // ---------------------------------------------------------------------
  /* Get the DiffIndex file first and see if there are patches availabe 
@@@ -674,6 -625,7 +675,6 @@@ 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);
  }
                                                                        /*}}}*/
@@@ -741,7 -693,6 +742,7 @@@ void pkgAcqIndex::Done(string Message,u
           Status = StatAuthError;
           ErrorText = _("Hash Sum mismatch");
           Rename(DestFile,DestFile + ".FAILED");
 +       ReportMirrorFailure("HashChecksumFailure");
           return;
        }
        // Done, move it into position
@@@ -828,13 -779,6 +829,13 @@@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgA
                            string URI,string URIDesc,string ShortDesc) 
    : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
  {
 +}
 +                                                                      /*}}}*/
 +// AcqIndexTrans::Custom600Headers - Insert custom request headers    /*{{{*/
 +// ---------------------------------------------------------------------
 +string pkgAcqIndexTrans::Custom600Headers()
 +{
 +   return "\nFail-Ignore: true";
  }
                                                                        /*}}}*/
  // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
@@@ -939,9 -883,8 +940,9 @@@ void pkgAcqMetaSig::Done(string Message
        Rename(LastGoodSig, DestFile);
  
     // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
 -   new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
 -                     DestFile, IndexTargets, MetaIndexParser);
 +   new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, 
 +                     MetaIndexShortDesc,  DestFile, IndexTargets, 
 +                     MetaIndexParser);
  
  }
                                                                        /*}}}*/
@@@ -954,7 -897,7 +955,7 @@@ void pkgAcqMetaSig::Failed(string Messa
     {
        Item::Failed(Message,Cnf);
        // move the sigfile back on transient network failures 
 -      if(FileExists(DestFile))
 +      if(FileExists(LastGoodSig))
         Rename(LastGoodSig,Final);
  
        // set the status back to , Item::Failed likes to reset it
@@@ -1029,15 -972,6 +1030,15 @@@ void pkgAcqMetaIndex::Done(string Messa
     if (AuthPass == true)
     {
        AuthDone(Message);
 +
 +      // all cool, move Release file into place
 +      Complete = true;
 +
 +      string FinalFile = _config->FindDir("Dir::State::lists");
 +      FinalFile += URItoFileName(RealURI);
 +      Rename(DestFile,FinalFile);
 +      chmod(FinalFile.c_str(),0644);
 +      DestFile = FinalFile;
     }
     else
     {
@@@ -1089,15 -1023,22 +1090,15 @@@ void pkgAcqMetaIndex::RetrievalDone(str
        return;
     }
  
 -   // see if the download was a IMSHit
 +   // make sure to verify against the right file on I-M-S hit
     IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
 +   if(IMSHit)
 +   {
 +      string FinalFile = _config->FindDir("Dir::State::lists");
 +      FinalFile += URItoFileName(RealURI);
 +      DestFile = FinalFile;
 +   }
     Complete = true;
 -
 -   string FinalFile = _config->FindDir("Dir::State::lists");
 -   FinalFile += URItoFileName(RealURI);
 -
 -   // If we get a IMS hit we can remove the empty file in partial
 -   // othersie we move the file in place
 -   if (IMSHit)
 -      unlink(DestFile.c_str());
 -   else
 -      Rename(DestFile,FinalFile);
 -
 -   chmod(FinalFile.c_str(),0644);
 -   DestFile = FinalFile;
  }
                                                                        /*}}}*/
  void pkgAcqMetaIndex::AuthDone(string Message)                                /*{{{*/
     QueueIndexes(true);
  
     // Done, move signature file into position
 -
     string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
        URItoFileName(RealURI) + ".gpg";
     Rename(SigFile,VerifiedSigFile);
@@@ -1164,13 -1106,16 +1165,16 @@@ void pkgAcqMetaIndex::QueueIndexes(boo
              return;
           }
        }
-       
-       // Queue Packages file (either diff or full packages files, depending
-       // on the users option)
-       if(_config->FindB("Acquire::PDiffs", true) == true) 
+       /* Queue Packages file (either diff or full packages files, depending
+          on the users option) - we also check if the PDiff Index file is listed
+          in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this
+          instead, but passing the required info to it is to much hassle */
+       if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false ||
+         MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true))
         new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
                             (*Target)->ShortDesc, ExpectedIndexHash);
-       else 
+       else
         new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
                            (*Target)->ShortDesc, ExpectedIndexHash);
     }
@@@ -1236,6 -1181,17 +1240,17 @@@ bool pkgAcqMetaIndex::VerifyVendor(stri
        Transformed = "";
     }
  
+    if (_config->FindB("Acquire::Check-Valid-Until", true) == true &&
+        MetaIndexParser->GetValidUntil() > 0) {
+       time_t const invalid_since = time(NULL) - MetaIndexParser->GetValidUntil();
+       if (invalid_since > 0)
+        // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
+        // the time since then the file is invalid - formated in the same way as in
+        // the download progress display (e.g. 7d 3h 42min 1s)
+        return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"),
+                             RealURI.c_str(), TimeToStr(invalid_since).c_str());
+    }
     if (_config->FindB("Debug::pkgAcquire::Auth", false)) 
     {
        std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl;
  //       return false;
        if (!Transformed.empty())
        {
-          _error->Warning("Conflicting distribution: %s (expected %s but got %s)",
+          _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
                           Desc.Description.c_str(),
                           Transformed.c_str(),
                           MetaIndexParser->GetDist().c_str());
@@@ -1270,30 -1226,30 +1285,30 @@@ void pkgAcqMetaIndex::Failed(string Mes
  {
     if (AuthPass == true)
     {
 -      // if we fail the authentication but got the file via a IMS-Hit 
 -      // this means that the file wasn't downloaded and that it might be
 -      // just stale (server problem, proxy etc). we delete what we have
 -      // queue it again without i-m-s 
 -      // alternatively we could just unlink the file and let the user try again
 -      if (IMSHit)
 +      // gpgv method failed, if we have a good signature 
 +      string LastGoodSigFile = _config->FindDir("Dir::State::lists") +
 +       "partial/" + URItoFileName(RealURI) + ".gpg.reverify";
 +      if(FileExists(LastGoodSigFile))
        {
 -       Complete = false;
 -       Local = false;
 -       AuthPass = false;
 -       unlink(DestFile.c_str());
 -
 -       DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 -       DestFile += URItoFileName(RealURI);
 -       Desc.URI = RealURI;
 -       QueueURI(Desc);
 +       string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
 +          URItoFileName(RealURI) + ".gpg";
 +       Rename(LastGoodSigFile,VerifiedSigFile);
 +       Status = StatTransientNetworkError;
 +       _error->Warning(_("A error occurred during the signature "
 +                         "verification. The repository is not updated "
 +                         "and the previous index files will be used."
 +                         "GPG error: %s: %s\n"),
 +                       Desc.Description.c_str(),
 +                       LookupTag(Message,"Message").c_str());
 +       RunScripts("APT::Update::Auth-Failure");
         return;
 +      } else {
 +       _error->Warning(_("GPG error: %s: %s"),
 +                       Desc.Description.c_str(),
 +                       LookupTag(Message,"Message").c_str());
        }
 -
        // gpgv method failed 
 -      _error->Warning("GPG error: %s: %s",
 -                      Desc.Description.c_str(),
 -                      LookupTag(Message,"Message").c_str());
 -
 +      ReportMirrorFailure("GPGFailure");
     }
  
     // No Release file was present, or verification failed, so fall
diff --combined apt-pkg/acquire-item.h
index 8f35c0dbfadfb3c82f8706c308a51757af461834,36fc53b92eb7c4fbdb9e28a01d287de0e4bfbbd5..943c61876c6e6a8938bc7289a68bf9828f065f21
@@@ -112,10 -112,10 +112,10 @@@ class pkgAcquire::Item : public WeakPoi
     string ErrorText;
  
     /** \brief The size of the object to fetch. */
-    unsigned long FileSize;
+    unsigned long long FileSize;
  
     /** \brief How much of the object was already fetched. */
-    unsigned long PartialSize;
+    unsigned long long PartialSize;
  
     /** \brief If not \b NULL, contains the name of a subprocess that
      *  is operating on this object (for instance, "gzip" or "gpgv").
      *  download progress indicator's overall statistics.
      */
     bool Local;
 +   string UsedMirror;
  
     /** \brief The number of fetch queues into which this item has been
      *  inserted.
  
     /** \return \b true if this object is being fetched from a trusted source. */
     virtual bool IsTrusted() {return false;};
 +   
 +   // report mirror problems
 +   /** \brief Report mirror problem
 +    * 
 +    *  This allows reporting mirror failures back to a centralized
 +    *  server. The apt-report-mirror-failure script is called for this
 +    * 
 +    *  \param FailCode A short failure string that is send
 +    */
 +   void ReportMirrorFailure(string FailCode);
 +
  
     /** \brief Initialize an item.
      *
@@@ -563,8 -551,7 +563,8 @@@ class pkgAcqIndex : public pkgAcquire::
      *  fallback is ".gz" or none.
      */
     pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
 -             string ShortDesc, HashString ExpectedHash, string compressExt="");
 +             string ShortDesc, HashString ExpectedHash, 
 +             string compressExt="");
  };
                                                                        /*}}}*/
  /** \brief An acquire item that is responsible for fetching a         {{{
@@@ -579,7 -566,6 +579,7 @@@ class pkgAcqIndexTrans : public pkgAcqI
     public:
    
     virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
 +   virtual string Custom600Headers();
  
     /** \brief Create a pkgAcqIndexTrans.
      *
@@@ -628,6 -614,7 +628,6 @@@ class pkgAcqMetaSig : public pkgAcquire
     /** \brief The last good signature file */
     string LastGoodSig;
  
 -
     /** \brief The fetch request that is currently being processed. */
     pkgAcquire::ItemDesc Desc;
  
index 6e021a445709233553c27450e0b869f454662729,b82dceecb4997175b30ffbaf4552cd752c4b99e6..17d52cf518b6c4f81c42706e8d30873dd7854946
@@@ -96,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");
@@@ -187,8 -184,6 +187,8 @@@ void pkgAcqMethod::URIDone(FetchResult 
        End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str());
     if (Res.SHA256Sum.empty() == false)
        End += snprintf(End,sizeof(S)-50 - (End - S),"SHA256-Hash: %s\n",Res.SHA256Sum.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();
@@@ -378,10 -373,9 +378,10 @@@ int pkgAcqMethod::Run(bool Single
            
            Tmp->Uri = LookupTag(Message,"URI");
            Tmp->DestFile = LookupTag(Message,"FileName");
-           if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
+           if (RFC1123StrToTime(LookupTag(Message,"Last-Modified").c_str(),Tmp->LastModified) == false)
               Tmp->LastModified = 0;
            Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
 +          Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);
            Tmp->Next = 0;
            
            // Append it to the list
diff --combined apt-pkg/deb/debsystem.cc
index ef5ec97032126ecd21ab2720cc0603f402d784d0,31c26ab2fee62f1bc1db4e246cc6aa878a29a2e1..7056d771d9e3755f49bc92fff096e12b740b6f36
@@@ -18,6 -18,7 +18,6 @@@
  #include <apt-pkg/error.h>
  #include <apt-pkg/fileutl.h>
  #include <apti18n.h>
 -    
  #include <sys/types.h>
  #include <unistd.h>
  #include <dirent.h>
@@@ -78,15 -79,8 +78,15 @@@ bool debSystem::Lock(
     {
        close(LockFD);
        LockFD = -1;
 +      const char *cmd;
 +      if (getenv("SUDO_USER") != NULL)
 +       cmd = "sudo dpkg --configure -a";
 +      else
 +       cmd = "dpkg --configure -a";
 +      // TRANSLATORS: the %s contains the recovery command, usually
 +      //              dpkg --configure -a
        return _error->Error(_("dpkg was interrupted, you must manually "
 -                             "run 'dpkg --configure -a' to correct the problem. "));
 +                             "run '%s' to correct the problem. "), cmd);
     }
  
         LockCount++;
@@@ -164,7 -158,7 +164,7 @@@ bool debSystem::Initialize(Configuratio
     /* These really should be jammed into a generic 'Local Database' engine
        which is yet to be determined. The functions in pkgcachegen should
        be the only users of these */
-    Cnf.CndSet("Dir::State::userstatus","status.user"); // Defunct
+    Cnf.CndSet("Dir::State::extended_states", Cnf.FindDir("Dir::State").append("extended_states"));
     Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status");
     Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg");
  
diff --combined apt-pkg/deb/dpkgpm.cc
index 95e3bafdcd3599b9232fa80c8168570c3b791429,0ac6ac168d80e0fc65e8849a66b3d75df95add87..9af7a0792d1b5c79439b2003af229cf5d3c4c46f
@@@ -12,7 -12,6 +12,7 @@@
  #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 <apti18n.h>
  #include <apt-pkg/fileutl.h>
  #include <stdlib.h>
  #include <fcntl.h>
  #include <sys/select.h>
 +#include <sys/stat.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  #include <signal.h>
  #include <errno.h>
 +#include <string.h>
  #include <stdio.h>
  #include <string.h>
  #include <algorithm>
@@@ -357,6 -354,7 +357,6 @@@ bool pkgDPkgPM::RunScriptsWithPkgs(cons
  
     return true;
  }
 -
                                                                        /*}}}*/
  // DPkgPM::DoStdin - Read stdin and pass to slave pty                 /*{{{*/
  // ---------------------------------------------------------------------
@@@ -427,7 -425,7 +427,7 @@@ void pkgDPkgPM::ProcessDpkgStatusLine(i
        'processing: trigproc: trigger'
            
     */
 -   char* list[5];
 +   char* list[6];
     //        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
         std::clog << "send: '" << status.str() << "'" << endl;
  
        if (strncmp(action, "disappear", strlen("disappear")) == 0)
-        disappearedPkgs.insert(string(pkg_or_trigger));
+        handleDisappearAction(pkg_or_trigger);
        return;
     }
  
     if(strncmp(action,"error",strlen("error")) == 0)
     {
 +      // urgs, sometime has ":" in its error string so that we
 +      // end up with the error message split between list[3]
 +      // and list[4], e.g. the message: 
 +      // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..."
 +      // concat them again
 +      if( list[4] != NULL )
 +       list[3][strlen(list[3])] = ':';
 +
        status << "pmerror:" << list[1]
             << ":"  << (PackagesDone/float(PackagesTotal)*100.0) 
             << ":" << list[3]
         write(OutStatusFd, status.str().c_str(), status.str().size());
        if (Debug == true)
         std::clog << "send: '" << status.str() << "'" << endl;
 +      pkgFailures++;
 +      WriteApportReport(list[1], list[3]);
        return;
     }
     else if(strncmp(action,"conffile",strlen("conffile")) == 0)
                << " action: " << action << endl;
  }
                                                                        /*}}}*/
+ // DPkgPM::handleDisappearAction                                      /*{{{*/
+ void pkgDPkgPM::handleDisappearAction(string const &pkgname)
+ {
+    // record the package name for display and stuff later
+    disappearedPkgs.insert(pkgname);
+    pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname);
+    if (unlikely(Pkg.end() == true))
+       return;
+    // the disappeared package was auto-installed - nothing to do
+    if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+       return;
+    pkgCache::VerIterator PkgVer = Pkg.CurrentVer();
+    if (unlikely(PkgVer.end() == true))
+       return;
+    /* search in the list of dependencies for (Pre)Depends,
+       check if this dependency has a Replaces on our package
+       and if so transfer the manual installed flag to it */
+    for (pkgCache::DepIterator Dep = PkgVer.DependsList(); Dep.end() != true; ++Dep)
+    {
+       if (Dep->Type != pkgCache::Dep::Depends &&
+         Dep->Type != pkgCache::Dep::PreDepends)
+        continue;
+       pkgCache::PkgIterator Tar = Dep.TargetPkg();
+       if (unlikely(Tar.end() == true))
+        continue;
+       // the package is already marked as manual
+       if ((Cache[Tar].Flags & pkgCache::Flag::Auto) != pkgCache::Flag::Auto)
+        continue;
+       pkgCache::VerIterator TarVer = Tar.CurrentVer();
+       for (pkgCache::DepIterator Rep = TarVer.DependsList(); Rep.end() != true; ++Rep)
+       {
+        if (Rep->Type != pkgCache::Dep::Replaces)
+           continue;
+        if (Pkg != Rep.TargetPkg())
+           continue;
+        // okay, they are strongly connected - transfer manual-bit
+        if (Debug == true)
+           std::clog << "transfer manual-bit from disappeared Â»" << pkgname << "« to Â»" << Tar.FullName() << "«" << std::endl;
+        Cache[Tar].Flags &= ~Flag::Auto;
+        break;
+       }
+    }
+ }
+                                                                       /*}}}*/
  // DPkgPM::DoDpkgStatusFd                                             /*{{{*/
  // ---------------------------------------------------------------------
  /*
@@@ -580,15 -613,15 +625,15 @@@ void pkgDPkgPM::DoDpkgStatusFd(int stat
  }
                                                                        /*}}}*/
  // DPkgPM::WriteHistoryTag                                            /*{{{*/
- void pkgDPkgPM::WriteHistoryTag(string tag, string value)
+ void pkgDPkgPM::WriteHistoryTag(string const &tag, string value)
  {
-    if (value.size() > 0)
-    {
-       // poor mans rstrip(", ")
-       if (value[value.size()-2] == ',' && value[value.size()-1] == ' ')
-        value.erase(value.size() - 2, 2);
-       fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
-    }
+    size_t const length = value.length();
+    if (length == 0)
+       return;
+    // poor mans rstrip(", ")
+    if (value[length-2] == ',' && value[length-1] == ' ')
+       value.erase(length - 2, 2);
+    fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
  }                                                                     /*}}}*/
  // DPkgPM::OpenLog                                                    /*{{{*/
  bool pkgDPkgPM::OpenLog()
@@@ -675,7 -708,22 +720,22 @@@ bool pkgDPkgPM::CloseLog(
  
     if(history_out)
     {
-       if (dpkg_error.size() > 0)
+       if (disappearedPkgs.empty() == false)
+       {
+        string disappear;
+        for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
+             d != disappearedPkgs.end(); ++d)
+        {
+           pkgCache::PkgIterator P = Cache.FindPkg(*d);
+           disappear.append(*d);
+           if (P.end() == true)
+              disappear.append(", ");
+           else
+              disappear.append(" (").append(Cache[P].CurVersion).append("), ");
+        }
+        WriteHistoryTag("Disappeared", disappear);
+       }
+       if (dpkg_error.empty() == false)
         fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
        fprintf(history_out, "End-Date: %s\n", timestr);
        fclose(history_out);
@@@ -1187,186 -1235,3 +1247,186 @@@ 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", false) == false)
 +   {
 +      std::clog << "configured to not write apport reports" << std::endl;
 +      return;
 +   }
 +
 +   // only report the first errors
 +   if(pkgFailures > _config->FindI("APT::Apport::MaxReports", 3))
 +   {
 +      std::clog << _("No apport report written because MaxReports is reached already") << std::endl;
 +      return;
 +   }
 +
 +   // check if its not a follow up error 
 +   const char *needle = dgettext("dpkg", "dependency problems - leaving unconfigured");
 +   if(strstr(errormsg, needle) != NULL) {
 +      std::clog << _("No apport report written because the error message indicates its a followup error from a previous failure.") << std::endl;
 +      return;
 +   }
 +
 +   // do not report disk-full failures 
 +   if(strstr(errormsg, strerror(ENOSPC)) != NULL) {
 +      std::clog << _("No apport report written because the error message indicates a disk full error") << std::endl;
 +      return;
 +   }
 +
 +   // do not report out-of-memory failures 
 +   if(strstr(errormsg, strerror(ENOMEM)) != NULL) {
 +      std::clog << _("No apport report written because the error message indicates a out of memory error") << std::endl;
 +      return;
 +   }
 +
 +   // do not report dpkg I/O errors
 +   // XXX - this message is localized, but this only matches the English version.  This is better than nothing.
 +   if(strstr(errormsg, "short read in buffer_copy (")) {
 +      std::clog << _("No apport report written because the error message indicates a dpkg I/O error") << std::endl;
 +      return;
 +   }
 +
 +   // get the pkgname and reportfile
 +   pkgname = flNotDir(pkgpath);
 +   pos = pkgname.find('_');
 +   if(pos != string::npos)
 +      pkgname = pkgname.substr(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);
 +   if (Ver.end() == true)
 +      return;
 +   pkgver = Ver.VerStr() == NULL ? "unknown" : Ver.VerStr();
 +   pkgRecords Recs(Cache);
 +   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
 +   srcpkgname = Parse.SourcePkg();
 +   if(srcpkgname.empty())
 +      srcpkgname = pkgname;
 +
 +   // if the file exists already, we check:
 +   // - if 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);
 +
 +   // ensure that the log is flushed
 +   if(term_out)
 +      fflush(term_out);
 +
 +   // attach terminal log it if we have it
 +   string logfile_name = _config->FindFile("Dir::Log::Terminal");
 +   if (!logfile_name.empty())
 +   {
 +      FILE *log = NULL;
 +      char buf[1024];
 +
 +      fprintf(report, "DpkgTerminalLog:\n");
 +      log = fopen(logfile_name.c_str(),"r");
 +      if(log != NULL)
 +      {
 +       while( fgets(buf, sizeof(buf), log) != NULL)
 +          fprintf(report, " %s", buf);
 +       fclose(log);
 +      }
 +   }
 +
 +   // log the ordering 
 +   const char *ops_str[] = {"Install", "Configure","Remove","Purge"};
 +   fprintf(report, "AptOrdering:\n");
 +   for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
 +      fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]);
 +
 +   // attach dmesg log (to learn about segfaults)
 +   if (FileExists("/bin/dmesg"))
 +   {
 +      FILE *log = NULL;
 +      char buf[1024];
 +
 +      fprintf(report, "Dmesg:\n");
 +      log = popen("/bin/dmesg","r");
 +      if(log != NULL)
 +      {
 +       while( fgets(buf, sizeof(buf), log) != NULL)
 +          fprintf(report, " %s", buf);
 +       fclose(log);
 +      }
 +   }
 +
 +   // attach df -l log (to learn about filesystem status)
 +   if (FileExists("/bin/df"))
 +   {
 +      FILE *log = NULL;
 +      char buf[1024];
 +
 +      fprintf(report, "Df:\n");
 +      log = popen("/bin/df -l","r");
 +      if(log != NULL)
 +      {
 +       while( fgets(buf, sizeof(buf), log) != NULL)
 +          fprintf(report, " %s", buf);
 +       fclose(log);
 +      }
 +   }
 +
 +   fclose(report);
 +
 +}
 +                                                                      /*}}}*/
diff --combined apt-pkg/deb/dpkgpm.h
index ce3e20f2e91e57b9620855d4e6044928cecd9423,9a4478f7cd018887d567378a5525ef2ffd8f0b43..b7b5a6def6243f877cf3056fa78901fe6a054fc1
@@@ -32,8 -32,22 +32,23 @@@ class pkgDPkgPM : public pkgPackageMana
     FILE *history_out;
     string dpkg_error;
  
+    /** \brief record the disappear action and handle accordingly
+       dpkg let packages disappear then they have no files any longer and
+       nothing depends on them. We need to collect this as dpkg as well as
+       APT doesn't know beforehand that the package will disappear, so the
+       only possible option is to tell the user afterwards about it.
+       To enhance the experience we also try to forward the auto-install
+       flag so the disappear-causer(s) are not autoremoved next time -
+       for the transfer to happen the disappeared version needs to depend
+       on the package the flag should be forwarded to and this package
+       needs to declare a Replaces on the disappeared package.
+       \param pkgname Name of the package that disappeared
+    */
+    void handleDisappearAction(string const &pkgname);
     protected:
 +   int pkgFailures;
  
     // progress reporting
     struct DpkgState 
@@@ -50,7 -64,6 +65,7 @@@
     // the int is the state that is already done (e.g. a package that is
     // going to be install is already in state "half-installed")
     map<string,unsigned int> PackageOpsDone;
 +
     // progress reporting
     unsigned int PackagesDone;
     unsigned int PackagesTotal;
     // Helpers
     bool RunScriptsWithPkgs(const char *Cnf);
     bool SendV2Pkgs(FILE *F);
-    void WriteHistoryTag(string tag, string value);
+    void WriteHistoryTag(string const &tag, string value);
  
 +   // apport integration
 +   void WriteApportReport(const char *pkgpath, const char *errormsg);
 +
     // dpkg log
     bool OpenLog();
     bool CloseLog();
diff --combined apt-pkg/tagfile.cc
index e1f576875bc68646958c066db684f1cb9f6077fe,1394d7e24acba2256d4d836641ad0188b7445e97..96a681bec9f8ce9224192db4a50304b9492aa001
@@@ -365,6 -365,30 +365,30 @@@ signed int pkgTagSection::FindI(const c
     return Result;
  }
                                                                        /*}}}*/
+ // TagSection::FindULL - Find an unsigned long long integer           /*{{{*/
+ // ---------------------------------------------------------------------
+ /* */
+ unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long const &Default) const
+ {
+    const char *Start;
+    const char *Stop;
+    if (Find(Tag,Start,Stop) == false)
+       return Default;
+    // Copy it into a temp buffer so we can use strtoull
+    char S[100];
+    if ((unsigned)(Stop - Start) >= sizeof(S))
+       return Default;
+    strncpy(S,Start,Stop-Start);
+    S[Stop - Start] = 0;
+    
+    char *End;
+    unsigned long long Result = strtoull(S,&End,10);
+    if (S == End)
+       return Default;
+    return Result;
+ }
+                                                                       /*}}}*/
  // TagSection::FindFlag - Locate a yes/no type flag                   /*{{{*/
  // ---------------------------------------------------------------------
  /* The bits marked in Flag are masked on/off in Flags */
@@@ -409,7 -433,6 +433,7 @@@ static const char *iTFRewritePackageOrd
                            "Section",
                            "Installed-Size",
                            "Maintainer",
 +                          "Original-Maintainer",
                            "Architecture",
                            "Source",
                            "Version",
@@@ -439,7 -462,6 +463,7 @@@ static const char *iTFRewriteSourceOrde
                                        "Priority",
                                        "Section",
                                        "Maintainer",
 +                                    "Original-Maintainer",
                                        "Build-Depends",
                                        "Build-Depends-Indep",
                                        "Build-Conflicts",
diff --combined cmdline/apt-get.cc
index eaf04eee7c9d78f0c9058c3d825b0ebb5acba228,2340a7e85def73164138eb7591073fe745e4c03d..0ada46c73b598c128e29a54c14454e95f45b74ee
@@@ -40,7 -40,8 +40,8 @@@
  #include <apt-pkg/sptr.h>
  #include <apt-pkg/md5.h>
  #include <apt-pkg/versionmatch.h>
-     
+ #include <apt-pkg/cacheset.h>
  #include <config.h>
  #include <apti18n.h>
  
@@@ -90,14 -91,14 +91,14 @@@ class CacheFile : public pkgCacheFil
     bool BuildCaches(bool WithLock = true)
     {
        OpTextProgress Prog(*_config);
-       if (pkgCacheFile::BuildCaches(Prog,WithLock) == false)
+       if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false)
         return false;
        return true;
     }
     bool Open(bool WithLock = true) 
     {
        OpTextProgress Prog(*_config);
-       if (pkgCacheFile::Open(Prog,WithLock) == false)
+       if (pkgCacheFile::Open(&Prog,WithLock) == false)
         return false;
        Sort();
        
@@@ -837,9 -838,9 +838,9 @@@ bool InstallPackages(CacheFile &Cache,b
        return false;
  
     // Display statistics
-    double FetchBytes = Fetcher.FetchNeeded();
-    double FetchPBytes = Fetcher.PartialPresent();
-    double DebBytes = Fetcher.TotalNeeded();
+    unsigned long long FetchBytes = Fetcher.FetchNeeded();
+    unsigned long long FetchPBytes = Fetcher.PartialPresent();
+    unsigned long long DebBytes = Fetcher.TotalNeeded();
     if (DebBytes != Cache->DebSize())
     {
        c0out << DebBytes << ',' << Cache->DebSize() << endl;
@@@ -1780,51 -1781,24 +1781,24 @@@ bool DoInstall(CommandLine &CmdL
         Packages++;
         if (Pkg.end() == true)
         {
-           // Check if the name is a regex
-           const char *I;
-           for (I = S; *I != 0; I++)
-              if (*I == '?' || *I == '*' || *I == '|' ||
-                  *I == '[' || *I == '^' || *I == '$')
-                 break;
-           if (*I == 0)
+           APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out);
+           if (pkgset.empty() == true)
               return _error->Error(_("Couldn't find package %s"),S);
  
            // Regexs must always be confirmed
            ExpectedInst += 1000;
-        
-           // Compile the regex pattern
-           regex_t Pattern;
-           int Res;
-           if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
-                              REG_NOSUB)) != 0)
-           {
-              char Error[300];     
-              regerror(Res,&Pattern,Error,sizeof(Error));
-              return _error->Error(_("Regex compilation error - %s"),Error);
-           }
-        
-           // Run over the matches
            bool Hit = false;
-           for (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp)
+           for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
            {
-              if (regexec(&Pattern,Grp.Name(),0,0,0) != 0)
-                 continue;
-              Pkg = Grp.FindPkg("native");
-              if (unlikely(Pkg.end() == true))
-                 continue;
-              ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
-                       Pkg.Name(),S);
-           
               if (VerTag != 0)
                  if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
                     return false;
-           
               Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
                                   ExpectedInst,false);
            }
-           regfree(&Pattern);
-        
            if (Hit == false)
               return _error->Error(_("Couldn't find package %s"),S);
         }
@@@ -2306,33 -2280,6 +2280,33 @@@ bool DoSource(CommandLine &CmdL
        if (Last == 0)
         return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
        
 +      string srec = Last->AsStr();
 +      string::size_type pos = srec.find("\nVcs-");
 +      while (pos != string::npos)
 +      {
 +       pos += strlen("\nVcs-");
 +       string vcs = srec.substr(pos,srec.find(":",pos)-pos);
 +       if(vcs == "Browser") 
 +       {
 +          pos = srec.find("\nVcs-", pos);
 +          continue;
 +       }
 +       pos += vcs.length()+2;
 +       string::size_type epos = srec.find("\n", pos);
 +       string uri = srec.substr(pos,epos-pos).c_str();
 +       ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in "
 +                         "the '%s' version control system at:\n"
 +                         "%s\n"),
 +                Src.c_str(), vcs.c_str(), uri.c_str());
 +       if(vcs == "Bzr") 
 +          ioprintf(c1out,_("Please use:\n"
 +                           "bzr get %s\n"
 +                           "to retrieve the latest (possibly unreleased) "
 +                           "updates to the package.\n"),
 +                   uri.c_str());
 +       break;
 +      }
 +
        // Back track
        vector<pkgSrcRecords::File> Lst;
        if (Last->Files(Lst) == false)
     }
     
     // Display statistics
-    double FetchBytes = Fetcher.FetchNeeded();
-    double FetchPBytes = Fetcher.PartialPresent();
-    double DebBytes = Fetcher.TotalNeeded();
+    unsigned long long FetchBytes = Fetcher.FetchNeeded();
+    unsigned long long FetchPBytes = Fetcher.PartialPresent();
+    unsigned long long DebBytes = Fetcher.TotalNeeded();
  
     // Check for enough free space
     struct statvfs Buf;
@@@ -2995,6 -2942,7 +2969,6 @@@ int main(int argc,const char *argv[]
                                     {"remove",&DoInstall},
                                     {"purge",&DoInstall},
                                   {"autoremove",&DoInstall},
 -                                 {"purge",&DoInstall},
                                   {"markauto",&DoMarkAuto},
                                   {"unmarkauto",&DoMarkAuto},
                                     {"dist-upgrade",&DoDistUpgrade},
diff --combined debian/changelog
index 1740d196ca0e9766f7e6c31cf53cb44ccea20c8d,56a17eb38ea1a075ad152008d2087255ee085259..9135d523b37d5f19c164e4759c4b16d27f92083a
@@@ -1,27 -1,67 +1,88 @@@
- apt (0.7.26~exp6) experimental; urgency=low
+ apt (0.7.26~exp6) UNRELEASED; urgency=low
  
 +  [ Michael Vogt ]
 +  * merge the remaining Ubuntu change:
 +    - on gpg verification failure warn and restore the last known
 +      good state
 +    - on failure display the IP of the server (useful for servers
 +      that use round robin DNS)
 +    - support Original-Maintainer in RewritePackageOrder
 +    - enable cdrom autodetection via libudev by default
 +    - show messsage about Vcs in use when apt-get source is run for
 +      packages maintained in a Vcs
 +    - better support transitional packages with mark auto-installed. 
 +      when the transitional package is in "oldlibs" the new package
 +      is not marked auto installed (same is true for section
 +      metapackages)
 +    - provide new "deb mirror://archive.foo/mirrors.list sid main"
 +      method expects a list of mirrors (generated on the server e.g.
 +      via geoip) and will use that, including cycle on failure
 +    - write apport crash file on package failure (disabled by default
 +      on debian until apport is available)
 +    - support mirror failure reporting (disabled by default on debian)
++  
+   [ David Kalnischkies ]
+   * apt-pkg/deb/dpkgpm.cc:
+     - write Disappeared also to the history.log
+     - forward manual-installed bit on package disappearance
+   * apt-pkg/deb/debsystem.cc:
+     - add better config item for extended_states file
+   * apt-pkg/pkgcache.h:
+     - switch {,Install-}Size to unsigned long long
+   * apt-pkg/depcache.cc:
+     - do the autoremove mark process also for required packages to handle
+       these illegally depending on lower priority packages (Closes: #583517)
+     - try harder to find the other pseudo versions for autoremove multiarch
+     - correct "Dangerous iterator usage" pointed out by cppcheck
+     - deal with long long, not with int to remove 2GB Limit (LP: #250909)
+     - deprecate AddSize with Multiplier as it is unused and switch to
+       boolean instead to handle the sizes more gracefully.
+     - switch i{Download,Usr}Size from double to (un)signed long long
+   * apt-pkg/aptconfiguration.cc:
+     - remove duplicate architectures in getArchitectures()
+   * apt-pkg/indexrecords.{cc,h}:
+     - backport forgotten Valid-Until patch from the obsolete experimental
+       branch to prevent replay attacks better, thanks to Thomas Viehmann
+       for the initial patch! (Closes: #499897)
+     - add a constant Exists check for MetaKeys
+   * apt-pkg/acquire-item.cc:
+     - do not try PDiff if it is not listed in the Meta file
+   * apt-pkg/cacheiterator.h:
+     - let pkgCache::Iterator inherent std::iterator
+   * ftparchive/writer.h:
+     - add a virtual destructor to FTWScanner class (for cppcheck)
+   * apt-pkg/cacheset.{cc,h}:
+     - add simple wrapper around std::set for cache structures
+     - move regex magic from apt-get to new FromRegEx method
+     - move cmdline parsing from apt-cache to new FromCommandLine method
+     - support special release-modifier 'installed' and 'candidate'
+   * apt-pkg/contrib/cmdline.cc:
+     - fix segfault in SaveInConfig caused by writing over char[] sizes
+   * apt-pkg/pkgcache.cc:
+     - get the best matching arch package from a group with FindPreferredPkg
+   * cmdline/apt-cache.cc:
+     - make the search multiarch compatible by using GrpIterator instead
+     - use pkgCacheFile and the new CacheSets all over the place
+     - add --target-release option (Closes: #115520)
+     - accept pkg/release and pkg=version in show and co. (Closes: #236270)
+     - accept package versions in the unmet command
+   * cmdline/apt-get.cc:
+     - use unsigned long long instead of double to store values it gets
+   * apt-pkg/cachefile.{cc,h}:
+     - split Open() into submethods to be able to build only parts
+     - make the OpProgress optional in the Cache buildprocess
+     - store also the SourceList we use internally for export
+   * doc/apt.conf.5.xml:
+     - document the new Valid-Until related options
+   * apt-pkg/contrib/strutl.cc:
+     - split StrToTime() into HTTP1.1 and FTP date parser methods and
+       use strptime() instead of some self-made scanf mangling
+     - use the portable timegm shown in his manpage instead of a strange
+       looking code copycat from wget
+   * ftparchive/writer.cc:
+     - add ValidTime option to generate a Valid-Until header in Release file
  
-  -- Michael Vogt <mvo@debian.org>  Wed, 09 Jun 2010 10:50:17 +0200
+  -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 09 Jun 2010 10:52:31 +0200
  
  apt (0.7.26~exp5) experimental; urgency=low
  
diff --combined methods/http.cc
index 3e2227f2b2e29366d6ad84ccf2cfca750fe44289,5fdc62696d2b2ca46116dfedafb06415051a8935..9fa74bffabff5362adaad277d6eec7d40e2650a4
@@@ -631,7 -631,7 +631,7 @@@ bool ServerState::HeaderLine(string Lin
     
     if (stringcasecmp(Tag,"Last-Modified:") == 0)
     {
-       if (StrToTime(Val,Date) == false)
+       if (RFC1123StrToTime(Val.c_str(), Date) == false)
         return _error->Error(_("Unknown date format"));
        return true;
     }
@@@ -953,9 -953,6 +953,9 @@@ HttpMethod::DealWithHeaders(FetchResul
        failure */
     if (Srv->Result < 200 || Srv->Result >= 300)
     {
 +      char err[255];
 +      snprintf(err,sizeof(err)-1,"HttpError%i",Srv->Result);
 +      SetFailReason(err);
        _error->Error("%u %s",Srv->Result,Srv->Code);
        if (Srv->HaveContent == true)
         return ERROR_WITH_CONTENT_PAGE;
@@@ -1369,4 -1366,15 +1369,4 @@@ bool HttpMethod::AutoDetectProxy(
  }
                                                                        /*}}}*/
  
 -int main()
 -{
 -   setlocale(LC_ALL, "");
 -   // ignore SIGPIPE, this can happen on write() if the socket
 -   // closes the connection (this is dealt with via ServerDie())
 -   signal(SIGPIPE, SIG_IGN);
 -
 -   HttpMethod Mth;
 -   return Mth.Loop();
 -}
 -
  
diff --combined test/pre-upload-check.py
index 97a0ec4c4c274929dc4f603b79642c20ab1bc912,e2dfecbd379e45090d092277ae567c77565dcbb9..f9da8f941eaedc93c507354c92a1c8f044339a73
@@@ -4,8 -4,6 +4,8 @@@ import sy
  import os
  import glob
  import os.path
 +import shutil
 +import time
  from subprocess import call, PIPE
  
  import unittest
  stdout = os.open("/dev/null",0) #sys.stdout
  stderr = os.open("/dev/null",0) # sys.stderr
  
 -apt_args = []  # ["-o","Debug::pkgAcquire::Auth=true"]
 +apt_args = [] 
 +#apt_args = ["-o","Debug::pkgAcquire::Auth=true"]
 +
 +class testAptAuthenticationReliability(unittest.TestCase):
 +    """
 +    test if the spec https://wiki.ubuntu.com/AptAuthenticationReliability 
 +    is properly implemented
 +    """
 +    #apt = "../bin/apt-get"
 +    apt = "apt-get"
 +
 +    def setUp(self):
 +        if os.path.exists("/tmp/autFailure"):
 +            os.unlink("/tmp/authFailure");
 +        if os.path.exists("/tmp/autFailure2"):
 +            os.unlink("/tmp/authFailure2");
 +    def testRepositorySigFailure(self):
 +        """
 +        test if a repository that used to be authenticated and fails on
 +        apt-get update refuses to update and uses the old state
 +        """
 +        # copy valid signatures into lists (those are ok, even
 +        # if the name is "-broken-" ...
 +        for f in glob.glob("./authReliability/lists/*"):
 +            shutil.copy(f,"/var/lib/apt/lists")
 +            # ensure we do *not* get a I-M-S hit
 +            os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0))
 +        res = call([self.apt,
 +                    "update",
 +                    "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure", 
 +                    "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure',
 +                   ] + apt_args,
 +                   stdout=stdout, stderr=stderr)
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"),
 +                     "The gpg file disappeared, this should not happen")
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"),
 +                     "The Packages file disappeared, this should not happen")
 +        self.assert_(os.path.exists("/tmp/authFailure"),
 +                     "The APT::Update::Auth-Failure script did not run (1)")
 +        # the same with i-m-s hit this time
 +        for f in glob.glob("./authReliability/lists/*"):
 +            shutil.copy(f,"/var/lib/apt/lists")
 +            os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time()))
 +        res = call([self.apt,
 +                    "update",
 +                    "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure",
 +                    "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure2',
 +                   ] + apt_args,
 +                   stdout=stdout, stderr=stderr)
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"),
 +                     "The gpg file disappeared, this should not happen")
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"),
 +                     "The Packages file disappeared, this should not happen")
 +        self.assert_(os.path.exists("/tmp/authFailure2"),
 +                     "The APT::Update::Auth-Failure script did not run (2)")
 +    def testRepositorySigGood(self):
 +        """
 +        test that a regular repository with good data stays good
 +        """
 +        res = call([self.apt,
 +                    "update",
 +                    "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good"
 +                   ] + apt_args,
 +                   stdout=stdout, stderr=stderr)
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"),
 +                     "The gpg file disappeared after a regular download, this should not happen")
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"),
 +                     "The Packages file disappeared, this should not happen")
 +        # test good is still good after non I-M-S hit and a previous files in lists/
 +        for f in glob.glob("./authReliability/lists/*"):
 +            shutil.copy(f,"/var/lib/apt/lists")
 +            # ensure we do *not* get a I-M-S hit
 +            os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0))
 +        res = call([self.apt,
 +                    "update",
 +                    "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good"
 +                   ] + apt_args,
 +                   stdout=stdout, stderr=stderr)
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"),
 +                     "The gpg file disappeared after a I-M-S hit, this should not happen")
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"),
 +                     "The Packages file disappeared, this should not happen")
 +        # test good is still good after I-M-S hit
 +        for f in glob.glob("./authReliability/lists/*"):
 +            shutil.copy(f,"/var/lib/apt/lists")
 +            # ensure we do get a I-M-S hit
 +            os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time()))
 +        res = call([self.apt,
 +                    "update",
 +                    "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good"
 +                   ] + apt_args,
 +                   stdout=stdout, stderr=stderr)
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"),
 +                     "The gpg file disappeared, this should not happen")
 +        self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"),
 +                     "The Packages file disappeared, this should not happen")
  
  
  class testAuthentication(unittest.TestCase):
                  self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0,
                               "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*"))
  
+     def testValid(self):
+         for f in glob.glob("testsources.list/sources.list*validuntil*"):
+             self._cleanup()
+             (prefix, testtype, result) = f.split("-")
+             expected_res = self._expectedRes(result)
+             cmd = ["update"]
+             res = call([self.apt,"-o","Dir::Etc::sourcelist=./%s" % f]+cmd+apt_args,
+                        stdout=stdout, stderr=stderr)
+             self.assert_(res == expected_res,
+                          "test '%s' failed (got %s expected %s" % (f,res,expected_res))
+             if expected_res == 0:
+                 self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0,
+                              "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*"))
  
  class testLocalRepositories(unittest.TestCase):
      " test local repository regressions "
@@@ -246,7 -163,6 +260,7 @@@ if __name__ == "__main__"
      if len(sys.argv) > 1 and sys.argv[1] == "-v":
          stdout = sys.stdout
          stderr = sys.stderr
 +    
 +    # run only one for now
 +    #unittest.main(defaultTest="testAptAuthenticationReliability")
      unittest.main()
 -
 -