}
                                                                        /*}}}*/
  
-    : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), needed_files(diffs)
 +// AcqIndexDiffs::AcqIndexDiffs - Constructor                 
 +// ---------------------------------------------------------------------
 +/* The package diff is added to the queue. one object is constructed
 + * for each diff and the index
 + */
 +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
 +                                 string URI,string URIDesc,string ShortDesc,
 +                                 string ExpectedMD5, vector<DiffInfo> diffs) 
-    if(needed_files.size() == 0)
++   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), available_patches(diffs)
 +{
 +   
 +   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 +   DestFile += URItoFileName(URI);
 +
 +   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
 +
 +   Desc.Description = URIDesc;
 +   Desc.Owner = this;
 +   Desc.ShortDesc = ShortDesc;
 +
 +   CurrentPackagesFile = _config->FindDir("Dir::State::lists");
 +   CurrentPackagesFile += URItoFileName(RealURI);
 +
 +   if(Debug) {
 +      std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " 
 +              << CurrentPackagesFile << std::endl;
 +   }
 +
 +   if(!FileExists(CurrentPackagesFile) || 
 +      !_config->FindB("Acquire::Diffs",true)) {
 +      // we don't have a pkg file or we don't want to queue
 +      if(Debug)
 +       std::clog << "No index file or canceld by user" << std::endl;
 +      Failed("", NULL);
 +      return;
 +   }
 +
-       string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | red  " + FinalFile + " >/dev/null 2>/dev/null";
++   if(available_patches.size() == 0)
 +      QueueDiffIndex(URI);
 +   else
 +      QueueNextDiff();
 +}
 +
 +void pkgAcqIndexDiffs::QueueDiffIndex(string URI)
 +{
 +   Desc.URI = URI + ".diff/Index";
 +   Desc.Description = Description + "IndexDiff";
 +   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 +   DestFile += URItoFileName(URI) + string(".IndexDiff");
 +
 +   if(Debug)
 +      std::clog << "QueueDiffIndex: " << Desc.URI << std::endl;
 +
 +   QueueURI(Desc);
 +}
 +
 +// AcqIndex::Custom600Headers - Insert custom request headers         /*{{{*/
 +// ---------------------------------------------------------------------
 +/* The only header we use is the last-modified header. */
 +string pkgAcqIndexDiffs::Custom600Headers()
 +{
 +   if(DestFile.rfind(".IndexDiff") == string::npos)
 +      return string("");
 +
 +   string Final = _config->FindDir("Dir::State::lists");
 +   Final += URItoFileName(RealURI) + string(".IndexDiff");
 +   
 +   if(Debug)
 +      std::clog << "Custom600Header-IMS: " << Final << std::endl;
 +
 +   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 pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 +{
 +   if(Debug)
 +      std::clog << "Failed(): " << Desc.URI << std::endl
 +              << "Falling back to big package file" << std::endl;
 +   new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc, 
 +                 ExpectedMD5);
 +   Finish();
 +}
 +
 +
 +// helper that cleans the item out of the fetcher queue
 +void pkgAcqIndexDiffs::Finish(bool allDone)
 +{
 +   // we restore the original name, this is required, otherwise
 +   // the file will be cleaned
 +   if(allDone) {
 +      // this is for the "real" finish
 +      DestFile = _config->FindDir("Dir::State::lists");
 +      DestFile += URItoFileName(RealURI);
 +      Complete = true;
 +      Dequeue();
 +      if(Debug)
 +       std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl;
 +      return;
 +
 +   }
 +
 +   if(Debug)
 +      std::clog << "Finishing: " << Desc.URI << std::endl;
 +   Complete = false;
 +   Status = StatDone;
 +   Dequeue();
 +   return;
 +}
 +
 +
 +// this needs to be rewriten to not depend on the external ed
 +bool pkgAcqIndexDiffs::ApplyDiff(string PatchFile)
 +{
 +   char *error;
 +   int res=0;
 +
 +   string FinalFile = _config->FindDir("Dir::State::lists");
 +   FinalFile += URItoFileName(RealURI);
 +
 +   int Process = ExecFork();
 +   if (Process == 0)
 +   {
 +      chdir(_config->FindDir("Dir::State::lists").c_str());
-    // FIXME: don't use the needed_files[0] but check sha1 and search
-    //        for the right patch in needed_files
-    //        -> and rename needed_files to "available_patches" 
++      // for some reason "red" fails with the pdiffs from p.d.o/~aba ?!? 
++      string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | /bin/ed  " + FinalFile + " >/dev/null 2>/dev/null";
 +      if(Debug)
 +       std::clog << "Runing: " << cmd << std::endl;
 +      res = system(cmd.c_str());
 +      _exit(WEXITSTATUS(res));
 +   }
 +   if(!ExecWait(Process, error, true)) {
 +      //_error->Error("Patch failed: %s ", error);
 +      return false;
 +   }
 +
 +   return true;
 +}
 +
 +bool pkgAcqIndexDiffs::QueueNextDiff()
 +{
-    // queue diff
-    Desc.URI = string(RealURI) + string(".diff/") + needed_files[0].file + string(".gz");
-    Desc.Description = needed_files[0].file + string(".pdiff");
++   // calc sha1 of the just patched file
++   string FinalFile = _config->FindDir("Dir::State::lists");
++   FinalFile += URItoFileName(RealURI);
++
++   FileFd fd(FinalFile, FileFd::ReadOnly);
++   SHA1Summation SHA1;
++   SHA1.AddFD(fd.Fd(), fd.Size());
++   string local_sha1 = string(SHA1.Result());
++
++   // see if we have a patch for it, the patch list must be ordered
++   for(vector<DiffInfo>::iterator I=available_patches.begin();
++       I != available_patches.end(); I++) {
++      // if the patch does not fit, it's not interessting
++      if((*I).sha1 != local_sha1)
++       available_patches.erase(I);
++   }
++
++   // error checking and falling back if no patch was found
++   if(available_patches.size() == 0) { 
++      Failed("", NULL);
++      return false;
++   }
 +
-    DestFile += URItoFileName(RealURI + string(".diff/") + needed_files[0].file);
++   // queue the right diff
++   Desc.URI = string(RealURI) + string(".diff/") + available_patches[0].file + string(".gz");
++   Desc.Description = available_patches[0].file + string(".pdiff");
 +
 +   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
-           needed_files.push_back(d);
++   DestFile += URItoFileName(RealURI + string(".diff/") + available_patches[0].file);
 +
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
 +   
 +   QueueURI(Desc);
 +
 +   return true;
 +}
 +
 +bool pkgAcqIndexDiffs::ParseIndexDiff(string IndexDiffFile)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile 
 +              << std::endl;
 +   
 +   FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
 +   pkgTagFile TF(&Fd);
 +   if (_error->PendingError() == true)
 +      return false;
 +   pkgTagSection Tags;
 +   if(TF.Step(Tags) == true)
 +   {
 +      string local_sha1;
 +      string tmp = Tags.FindS("SHA1-Current");
 +      std::stringstream ss(tmp);
 +      ss >> ServerSha1;
 +
 +      FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
 +      SHA1Summation SHA1;
 +      SHA1.AddFD(fd.Fd(), fd.Size());
 +      local_sha1 = string(SHA1.Result());
 +
 +      if(local_sha1 == ServerSha1) {
 +       if(Debug)
 +          std::clog << "Package file is up-to-date" << std::endl;
 +       Finish(true);
 +       return true;
 +      }
 +      if(Debug)
 +       std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
 +
 +      // check the historie and see what patches we need
 +      string history = Tags.FindS("SHA1-History");     
 +      std::stringstream hist(history);
 +      DiffInfo d;
 +      string size;
 +      bool found = false;
 +      while(hist >> d.sha1 >> size >> d.file) {
 +       d.size = atoi(size.c_str());
 +       if(d.sha1 == local_sha1) 
 +          found=true;
 +       if(found) {
 +          if(Debug)
 +             std::clog << "Need to get diff: " << d.file << std::endl;
-                             ExpectedMD5, needed_files);
++          available_patches.push_back(d);
 +       }
 +      }
 +      // no information how to get the patches, bail out
 +      if(!found) {
 +       if(Debug)
 +          std::clog << "Can't find a patch in the index file" << std::endl;
 +       // Failed will queue a big package file
 +       Failed("", NULL);
 +      } else {
 +       // queue the diffs
 +       new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
-       needed_files.erase(needed_files.begin());
++                            ExpectedMD5, available_patches);
 +       Finish();
 +       return true;
 +      }
 +   }
 +
 +   return false;
 +}
 +
 +
 +void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
 +                          pkgAcquire::MethodConfig *Cnf)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl;
 +
 +   Item::Done(Message,Size,Md5Hash,Cnf);
 +
 +   int len = Desc.URI.size();
 +   // sucess in downloading the index
 +   if(Desc.URI.substr(len-strlen("Index"),len-1) == "Index") {
 +
 +      // rename
 +      string FinalFile = _config->FindDir("Dir::State::lists");
 +      FinalFile += URItoFileName(RealURI) + string(".IndexDiff");
 +      if(Debug)
 +       std::clog << "Renaming: " << DestFile << " -> " << FinalFile 
 +                 << std::endl;
 +      Rename(DestFile,FinalFile);
 +      chmod(FinalFile.c_str(),0644);
 +      DestFile = FinalFile;
 +
 +      if(!ParseIndexDiff(DestFile))
 +       return Failed("", NULL);
 +      else 
 +       return Finish();
 +   }
 +
 +   // sucess in downloading a diff
 +   if(Desc.URI.find(".diff") != string::npos) {
 +      ApplyDiff(DestFile);
-       if(needed_files.size() > 0) {
++      available_patches.erase(available_patches.begin());
 +
-                             ExpectedMD5, needed_files);
++      if(available_patches.size() > 0) {
 +       new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
++                            ExpectedMD5, available_patches);
 +      } else {
 +       Finish(true);
 +       return;
 +      }
 +   }
 +
 +   Finish();
 +}
 +
 +
  // AcqIndex::AcqIndex - Constructor                                   /*{{{*/
  // ---------------------------------------------------------------------
  /* The package file is added to the queue and a second class is